buffer->CGImageRef->UIImage 的正确内存管理模式是什么?
我有一个函数,它接受一些位图数据并从中返回一个 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 后在此函数末尾释放像素,然后使用 UIImage,则会崩溃。如果我在创建 UIImage 后释放提供程序或 imageRef,我不会看到崩溃,但它们显然一直在传递像素,所以我对释放这些中间状态感到不安。
(我知道根据 CF 文档,我应该需要对后者调用释放,因为它们来自 Create 函数,但我可以在使用 UIImage 之前执行此操作吗?)大概我可以使用提供程序的 dealloc 回调来清理像素缓冲区,但还有什么呢?
谢谢!
I have a function that takes some bitmap data and returns a UIImage * from it. It looks something like so:
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];
}
Can anyone explain exactly who owns what memory here? I want to clean up properly, but I'm not sure how to do it safely. Docs are fuzzy on these. If I free
pixels at the end of this function after creating the UIImage, and then use the UIImage, I crash. If I Release the provider or the imageRef after creating the UIImage, I don't see a crash, but they're apparently passing the pixels all the way through, so I'm skittish about releasing these intermediate states.
(I know per CF docs that I should need to call release on both of the latter because they come from Create functions, but can I do that before the UIImage is used?) Presumably I can use the provider's dealloc callback to cleanup the pixels buffer, but what else?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这里的经验法则是“
-release
* 如果你不需要它”。因为之后您不再需要
provider
和imageRef
,所以您应该-release
所有它们,即pixel
不是通过引用计数管理,因此您需要告诉 CG API 在必要时为您释放它们。这样做:顺便说一句,您可以使用
+imageWithCGImage:
而不是[[[* alloc] initWithCGImage:] autorelease]
。更好的是,有+imageWithData:
所以你不需要搞乱 CG 和malloc
的东西。(*:除非
retainCount
从一开始就已经为零。)The thumb rule here is "
-release
* it if you don't need it".Because you no longer need
provider
andimageRef
afterwards, you should-release
all of them, i.e.pixel
is not managed by ref-counting, so you need to tell the CG API to free them for you when necessary. Do this:By the way, you can use
+imageWithCGImage:
instead of[[[* alloc] initWithCGImage:] autorelease]
. Even better, there is+imageWithData:
so you don't need to mess with the CG andmalloc
stuff.(*: Except when the
retainCount
is already supposedly zero from the beginning.)您拥有
pixels
缓冲区,因为您对它进行了 malloc。Core Graphics 遵循 Core Foundation 规则。您拥有该数据提供程序,因为您创建了它。
您没有提供释放回调,因此您仍然拥有
pixels
缓冲区。如果您提供了释放回调,则 CGDataProvider 对象将获得此处缓冲区的所有权。 (通常是个好主意。)您拥有 CGImage 对象,因为您创建了它。
您拥有 UIImage 对象,因为您分配了它。
您仍然拥有 CGImage 对象。如果 UIImage 对象想要拥有 CGImage 对象,它将保留它或创建自己的副本。
您放弃对图像的所有权。
因此,您的代码泄漏了像素(您没有将所有权转移给数据提供者,并且您自己没有释放它们)、数据提供者(您没有释放它)和 CGImage(您没有释放它) 。固定版本会将像素的所有权转移给数据提供者,并在 UIImage 准备就绪时释放数据提供者和 CGImage。或者,按照 KennyTM 的建议,使用
imageWithData:
。You own the
pixels
buffer because you mallocked it.Core Graphics follows the Core Foundation rules. You own the data provider because you Created it.
You didn't provide a release callback, so you still own the
pixels
buffer. If you had provided a release callback, the CGDataProvider object would take ownership of the buffer here. (Generally a good idea.)You own the CGImage object because you Created it.
You own the UIImage object because you allocked it.
You also still own the CGImage object. If the UIImage object wants to own the CGImage object, it will either retain it or make its own copy.
You give up your ownership of the image.
So your code leaks the pixels (you didn't transfer ownership to the data provider and you didn't release them yourself), the data provider (you didn't release it), and the CGImage (you didn't release it). A fixed version would transfer ownership of the pixels to the data provider, and would release both the data provider and the CGImage by the time the UIImage is ready. Or, just use
imageWithData:
, as KennyTM suggested.使用 CGImageCreate 后,我也遇到了 malloc/free 问题
我终于找到了很好又简单的解决方案。
我只是将 line: 替换
为:
之后我就可以释放 malloced 内存:
I also had problem with malloc/free after using CGImageCreate
I finally found good and simple solution.
I just replace line:
with:
Just after that i could free mallocked memory:
是的,这段代码让我感到恶心。作为一个古老的生活规则,我尽量不要在同一个函数/方法/选择器中混合和匹配 C 和 C++,以及 C/Objective-C。
把它分成两种方法怎么样?将此 makeAnImage 更改为 makeAnImageRef 并将 UIImage 创建拉到另一个 Obj-C 选择器中。
Aye, this code makes me queasy. As an old rule-to-live by, I try not to mix and match C and C++, and C/Objective-C in the same function/method/selector.
How about breaking this up into two methods. Have change this makeAnImage into makeAnImageRef and pull up the UIImage creation into another Obj-C selector.