我用一个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];
}
您的问题是所谓的“堆栈溢出”(您以前可能听说过)。
您的方法使用可变长度数组在堆栈上分配缓冲区:
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 ...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)