C和Objective-C-释放无符号字符指针的正确方法

6

在我的应用程序中,我使用以下函数创建一个未签名的字符指针:

- (unsigned char*)getRawData
{
// First get the image into your data buffer
CGImageRef image = [self CGImage];
NSUInteger width = CGImageGetWidth(image);
NSUInteger height = CGImageGetHeight(image);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

unsigned char *rawData = malloc(height * width * 4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);

CGContextSetBlendMode(context, kCGBlendModeCopy);

CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), image);
CGContextRelease(context);

// Now your rawData contains the image data in the RGBA8888 pixel format.

return rawData;
}

在另一个类中,我这样给指针分配了一个属性:self.bitmapData = [image getRawData];

在这个过程中,我应该在哪里释放那个malloc分配的内存?当我试图在dealloc中释放属性时,它会给我一个exc_bad_access错误。我感觉我在这里缺少了基本的C或Objective-C概念。非常感谢您的帮助。


你是怎样释放这个属性的? - iandotkelly
1
每个分配器都有一个成对的解分配器来释放已分配的对象。查看malloc的 man-page——但最好找到与您特定平台相关的文档——将解释应该使用什么;-) - user166390
我尝试了free(property),但似乎不正确,但我还是试了一下。 - Daniel G. Wilson
2个回答

6

关于在Objective-C中使用malloc/free的安全性有一个很好的讨论在这里

只要你正确地使用free()释放malloc()分配的内存,就应该没有问题。

我个人认为使用NSMutableData或NSMutableArray更加方便。如果你不需要终极性能,我不会直接使用C malloc/free语句。


这帮助我找到了答案,而这与我的使用无关。使用 free(self.property); 是不正确的。facepalm。我尝试了 free(property);,结果良好。将来,我相信我会使用 NSData 来避免 malloc 的麻烦。 - Daniel G. Wilson

4

解决这种问题的一种方法是使用NSMutableData,这样您就可以替换掉旧数据。

unsigned char *rawData = malloc(height * width * 4);

使用

myData = [[NSMutableData alloc] initWithCapacity:height * width * 4];
unsigned char *rawData = myData.mutableBytes;

你可以在释放函数中释放 myData。

或者你也可以这样做:

myData = [NSMutableData dataWithCapacity:height * width * 4];

这将意味着您的myData将在事件循环期间保持存在,您甚至可以更改getRawData方法的返回类型以返回NSMUtableData或NSData,并且这样它可以被代码中的其他部分保留。我只有在知道返回的数据将在对象的生命周期内可用时才返回原始字节,这样如果需要保存数据,我可以保留所有者类。Apple通常会使用


myData = [[NSMutableData alloc] initWithCapacity:height * width * 4];
unsigned char *rawData = myData.mutableBytes;

在使用自动释放池后,如果需要超出当前自动释放池生命周期的字节,则需要将其复制。


但这不是同样的问题吗,只是现在使用对象而不是原始指针?对象必须被释放,原始指针必须被释放。在这两种情况下,设计应该很清楚地表明它们何时可以被丢弃。 - Rudy Velthuis
更容易处理对象,因为您可以遵循保留/释放规则。如果您从方法中返回原始字节,您如何知道方法的调用者是否正确管理内存?如果方法的调用者对返回的字节不感兴趣,该怎么办?如果这些字节来自私有方法,那么您可以随心所欲地使用它们,但如果它是公共接口的一部分,则制作傻瓜式的东西,以便您不必记住6个月前写的方法不像通常的方式那样运行,只需遵循简单的规则即可。 - Nathan Day
这就是为什么我不会返回内存。我会告诉调用者需要多大的缓冲区,然后调用者可以向您分配一个缓冲区。您只需填充缓冲区即可。这样,所有权就更加清晰,我个人认为。 - Rudy Velthuis
是的,这是我经常采用的好方法,但在某些情况下,返回自动释放的NSData字节很有用。我认为一些NSString方法可以做到这一点,比如-[NSString UTF8String]。 - Nathan Day

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接