dataWithBytesNoCopy 和 dataWithBytes 之间的区别?

Difference between dataWithBytesNoCopy and dataWithBytes?

有什么区别

+ (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";

几天来我一直在研究这个问题:

但最后我发现了问题,在我的加密和解密函数中,我有这个:

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

+ dataWithBytes:length::

Creates and returns a data object containing a given number of bytes copied from a given buffer.

+ dataWithBytesNoCopy:length::

Creates and returns a data object that holds length bytes from the buffer bytes.

dataWithBytes 为数据复制缓冲区,而 NoCopy 版本没有。

重要说明:在dataWithBytesNoCopy:length:的讨论部分:

The returned object takes ownership of the bytes pointer and frees it on deallocation. Therefore, bytes must point to a memory block allocated with malloc.

这意味着使用此方法初始化实质上将内存的所有权交给 NSData 对象,一旦完成,该对象将使用 free 释放它。如果您尝试使用未使用 malloc 分配的内存对其进行初始化,您的应用程序将在数据对象被释放时崩溃。

dataWithBytesNoCopy 当你从其他地方得到缓冲区中的字节,并准备将它们交给 NSData 对象时很有用,并且不会在外面再次使用它们

如果您想使用自己管理的内存初始化数据,请使用+ dataWithBytesNoCopy:length:freeWhenDone:。如果缓冲区将永久存储在某处并且不会更改或释放,这将很有用。

但是,如果您不确定如何手动正确管理此内存,最好使用 dataWithBytes。其他方法是出于性能原因而存在的,因为避免复制大块数据可以节省大量时间,但如果您不确定如何使用它们,最好不要使用 - 最好不要使用不会崩溃的应用程序快速崩溃的应用程序。

[[NSData alloc] initWithBytes:buffer length:buflength] 创建一个包含从缓冲区字节复制的 buflength 字节的数据对象。

[NSData dataWithBytesNoCopy:buffer length:buflength] 创建一个数据对象,它保存来自缓冲区字节的 buflength 字节。返回的对象获得缓冲区指针的所有权并在释放时释放它。因此buffer必须指向一个用malloc分配的内存块。