什么是对buffer-> CGImageRef->的UIImage正确的内存管理模式?
-
22-09-2019 - |
题
我有一个功能,需要一些位图数据,并返回一个UIImage *从它。它看起来像这样:
UIImage * makeAnImage()
{
unsigned char * pixels = malloc(...);
// ...
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, pixelBufferSize, NULL);
CGImageRef imageRef = CGImageCreate(..., provider, ...);
UIImage * image = [[UIImage alloc] initWithCGImage:imageRef];
return [image autorelease];
}
谁能解释一下到底是谁在这里拥有什么内存?我想收拾妥当,但我不知道如何做到这一点安全。文档是对这些模糊。如果我在创建的UIImage后此功能结束free
像素,然后使用UIImage的,我崩溃。如果我放开提供商或创建的UIImage后imageRef,我没有看到崩溃,但他们显然经过像素一路过关斩将,所以我水性杨花释放这些中间状态。
(我知道每个CF的文档,我应该需要调用两个后者的释放,因为他们来自创建功能,但我能做到这一点使用的UIImage前?)大概我可以利用供应商的dealloc的回调清理像素缓冲区,但还有什么?
谢谢!
解决方案
在经验法则这里是“-release
*,如果你不需要它。”
由于您不再需要provider
和imageRef
之后,你应该-release
所有的人,即。
UIImage * image = [[UIImage alloc] initWithCGImage:imageRef];
CGDataProviderRelease(provider);
CGImageRelease(imageRef);
return [image autorelease];
pixel
不是由裁判计数管理的,所以你需要告诉CG API来释放他们为你需要的时候。做到这一点:
void releasePixels(void *info, const void *data, size_t size) {
free((void*)data);
}
....
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, pixelBufferSize, releasePixels);
顺便说一句,你可以使用+imageWithCGImage:
代替[[[* alloc] initWithCGImage:] autorelease]
。更妙的是,有+imageWithData:
,所以你不需要用CG和malloc
东西乱七八糟。
(*:除了当retainCount
已经推测从头零)
其他提示
unsigned char * pixels = malloc(...);
您拥有pixels
缓冲区,因为你mallocked它。
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, pixelBufferSize, NULL);
核心图形如下的核心基础的规则。你自己,因为你创建它的数据提供者。
您没有提供释放回调,所以你仍然拥有pixels
缓冲区。如果你提供了一个释放的回调,则CGDataProvider对象将采取缓冲的所有权这里。 (通常是个好主意。)
CGImageRef imageRef = CGImageCreate(..., provider, ...);
您拥有CGImage对象,因为你创造了它。
UIImage * image = [[UIImage alloc] initWithCGImage:imageRef];
您拥有UIImage对象,因为你allocked它。
您也仍然拥有CGImage对象。如果UIImage对象希望自己的CGImage对象,它要么保留,或使自己的副本。
return [image autorelease];
您放弃了自己的形象的所有权。
所以你的代码泄漏的像素(你没有所有权转移给数据提供者,你自己并没有释放出来),数据提供者(你不松开),和CGImage(你没有释放)。固定版本将转移像素所有权有关的数据提供者,并会释放两个数据提供者,由当时的UIImage准备的CGImage。或者,只要使用imageWithData:
,作为KennyTM建议。
unsigned char * pixels = malloc(...);
我也有使用malloc问题/免费使用CGImageCreate后 我终于找到好的和简单的解决方案。 我只替换行:
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, pixelBufferSize, NULL);
使用:
NSData *data = [NSData dataWithBytes:pixels length:pixelBufferSize];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
只需后,我可以释放mallocked存储器:
free (pixels);
埃,该代码使我反胃。作为一个老规则生存的,我尽量不混合,并在同一个函数/方法/选择器匹配C和C ++和C / Objective-C的。
如何打破这种一分为二的方法。需要更改此makeAnImage到makeAnImageRef和UIImage的创作拉起到另一个对象 - 选择。