-[NSInputStream read:maxLength:] throws an exception saying length is too big, but it isn't
cocoa-touch, ios, nsinputstream, objective-c, stack-overflow
Solution
Your problem is a so called "stack overflow" (you might have heard this before).
Your method allocates a buffer on the stack using a variable length array:
uint8_t buf[bufferSizeNumber];
When the size of the buffer is so large that it overflows the size of the current stack the behavior is undefined. Undefined behavior might result in a crash or just work as expected: just what you are observing.
512kB is a huge buffer, especially on iOS where background threads get a stack of exactly this size.
You should allocate it on the heap:
NSInteger bufferSizeNumber = 524288;
NSMutableData *myBuffer = [NSMutableData dataWithLength:bufferSizeNumber];
uint8_t *buf = [myBuffer mutableBytes];
unsigned int len = 0;
len = [_stream read:buf maxLength:bufferSizeNumber];
// more code ...
Problem
I use an `NSInputStream` to read data from a file. It will crash if `maxLength` is greater than 49152. When it crashes -- sometimes, but not every time, it gives this message: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:]: absurd length: 4294967295, maximum size: 2147483648 bytes' From my calculation, 524288 is still less than that maximum, and can fit in the return value. What did I miss? ``` - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { case NSStreamEventHasBytesAvailable: { NSInteger bufferSizeNumber = 524288; //this one will crash. // NSInteger bufferSizeNumber = 491520; // this one will work. uint8_t buf[bufferSizeNumber]; unsigned int len = 0; len = [_stream read:buf maxLength:bufferSizeNumber]; //crashing at this line // more code ... } // more code... } } ``` Edit: (I think this is critical part of that behavior) If I "start" in the background thread then the bufferSizeNumber behaves as described above. But if I "start" in the main thread, the bufferSizeNumber can go upto 943713 before it crashes. ``` - (void)start { _stream.delegate = self; [_stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [_stream open]; [[NSRunLoop currentRunLoop] run]; } ```