dataWithBytesNoCopy和dataWithBytes之间的区别?

时间:2015-05-19 12:44:23

标签: ios byte nsdata

之间有什么区别

+ (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不会为我释放它。

2 个答案:

答案 0 :(得分:6)

+ dataWithBytes:length:

  

创建并返回一个数据对象,该数据对象包含给定缓冲区中复制的给定字节数。

+ 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分配的内存块。