之间有什么区别
+ (instancetype)dataWithBytes:(const void *)bytes length:(NSUInteger)length;
和
+ (instancetype)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length;
另外,
+ (instancetype)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b;
如果b == YES
,它会在转换为数据后自动释放字节吗?
我正在开发一款应用程序,差不多完成了它。但最后一个问题是它在设备上运行时因内存错误而崩溃。它只在设备上崩溃,但在模拟器中它是完美的。
"malloc: * error for object 0x17415d0c0: Invalid pointer dequeued from free list * set a breakpoint in malloc_error_break to debug";
我已经在这个问题上工作了好几天: iOS - My app crashes with memory Error if only runs on Device
但最后我发现问题,在我的加密和解密功能中,我有这个:
Byte *buffer = (Byte*)malloc(asciiDataLength);
使用缓冲区处理后,我将其转换为NSData
:
NSData *plainData = [NSData dataWithBytesNoCopy:buffer length:asciiDataLength freeWhenDone:YES];
此代码导致我的应用程序不断崩溃,我将其更改为
NSData *plainData = [NSData dataWithBytes:buffer length:asciiDataLength];
free(buffer);
然后我的应用再也不会崩溃了。
所以,我必须自己释放字节,ARC不会为我释放它。
答案 0 :(得分:6)
创建并返回一个数据对象,该数据对象包含给定缓冲区中复制的给定字节数。
+ dataWithBytesNoCopy:length:
:
创建并返回一个数据对象,该数据对象包含缓冲区
bytes
中的长度字节。
dataWithBytes
为数据创建缓冲区的副本,而NoCopy
版本则没有。
重要提示:在dataWithBytesNoCopy:length:
的讨论部分:
返回的对象取得字节指针的所有权,释放取消分配。因此,
bytes
必须指向使用malloc
分配的内存块。
这意味着使用此方法初始化基本上将内存的所有权交给NSData
对象,一旦完成,将以free
释放它。如果您尝试使用未使用malloc
分配的内存对其进行初始化,则在取消分配数据对象时,您的应用程序将崩溃。
dataWithBytesNoCopy
非常有用,并且可以将它们交给NSData
对象,并且不会在外面再次使用它们那个。
如果您想使用自己管理的内存初始化数据,请使用+ dataWithBytesNoCopy:length:freeWhenDone:
。如果缓冲区将被持久存储在某处,而不是更改或释放,那么这很有用。
但是,如果您不确定如何手动正确管理此内存,最好使用dataWithBytes
。出于性能原因,存在其他方法,因为避免复制大块数据可以节省大量时间,但如果您不确定如何使用它们,那么最好不要 - 应用程序对于崩溃很快的应用程序来说,不会崩溃。
答案 1 :(得分:-1)
[[NSData alloc] initWithBytes:buffer length:buflength]创建一个包含从缓冲区字节复制的buflength字节的数据对象。
[NSData dataWithBytesNoCopy:buffer length:buflength]创建一个数据对象,该对象保存缓冲区字节中的buflength字节。返回的对象获取缓冲区指针的所有权,并在取消分配时释放它。因此,缓冲区必须指向使用malloc分配的内存块。