【问题标题】:-[NSInputStream read:maxLength:] throws an exception saying length is too big, but it isn't-[NSInputStream read:maxLength:] 抛出异常,说长度太大,但不是
【发布时间】:2014-02-22 15:47:56
【问题描述】:

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

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

*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“*** -[NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:]:荒谬的长度:4294967295,最大大小:2147483648 字节”

根据我的计算,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];
}

【问题讨论】:

  • 您的类型错误:maxLength 参数应该是无符号的,捕获返回值的变量必须是有符号的,因为负值表示读取失败.不过,这不会导致这个问题。
  • @JoshCaswell:感谢编辑。

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


【解决方案1】:

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

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

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

【讨论】:

  • @user523234 你想一起独处吗? :)
  • len 应该是 NSInteger,因为它可以是零或负数,表示错误!
  • @PeterLapisu 好点,即使不是 OP 遇到的错误的来源。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-23
  • 2010-12-09
  • 2011-05-30
  • 1970-01-01
  • 2019-05-26
相关资源
最近更新 更多