ios - -[NSInputStream 读取 :maxLength:] throws an exception saying length is too big, 但它不是

标签 ios objective-c cocoa-touch stack-overflow nsinputstream

我使用 NSInputStream 从文件中读取数据。如果 maxLength 大于 49152,它将崩溃。

当它崩溃时——有时,但不是每次,它都会给出这条消息:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:]: absurd length: 4294967295, maximum size: 2147483648 bytes'

根据我的计算,524288 仍然小于最大值,并且可以放入返回值中。我错过了什么?

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

编辑:(我认为这是该行为的关键部分)

如果我在后台线程中“启动”,则 bufferSizeNumber 的行为如上所述。但是,如果我在主线程中“启动”,则 bufferSizeNumber 在崩溃之前可以达到 943713。

- (void)start
{
    _stream.delegate = self;
    [_stream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                       forMode:NSDefaultRunLoopMode];
    [_stream open];
    [[NSRunLoop currentRunLoop] run];
}

最佳答案

您的问题是所谓的“堆栈溢出”(您以前可能听说过)。

您的方法使用可变长度数组在堆栈上分配缓冲区:

uint8_t buf[bufferSizeNumber];

当缓冲区的大小大到溢出当前堆栈的大小时,行为是未定义的。未定义的行为可能会导致崩溃或只是按预期工作:正是您所观察到的。

512kB 是一个巨大的缓冲区,尤其是在 iOS 上,后台线程得到的堆栈正是这个大小。

你应该在堆上分配它:

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

关于ios - -[NSInputStream 读取 :maxLength:] throws an exception saying length is too big, 但它不是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21956559/

相关文章:

ios - 值应四舍五入到最接近的十分之一或最接近的四分之一

objective-c - 从 NSArray 中的 NSNumber 获取整数值

ios - TouchID with KeyChain - 输入密码屏幕出现格式错误 (Swift)

ios - JSON 解析后, TableView 中的字符串打印不正确

objective-c - iPad 多个细节 View 和模型教程/示例

objective-c - 弹出其他 View Controller 时如何更改弹出 View 大小

ios - Swift:UISearchBar:单击搜索按钮时获取文本

ios - 数据未显示在标签中

生成视频缩略图的 iOS 代码返回 0 字节[]

iphone - UIApplicationDidFinishLaunchingNotification的使用