-[NSInputStream read:maxLength:] throws an exception saying length is too big, but it isn't

限于喜欢 提交于 2019-12-30 09:44:10

问题


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];
}

回答1:


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 ...


来源:https://stackoverflow.com/questions/21956559/nsinputstream-readmaxlength-throws-an-exception-saying-length-is-too-big-b

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!