另一款 iPhone - CGBitmapContextCreateImage 泄漏
就像这篇文章一样:
我有一个类似的问题。 create_bitmap_data_provider
中 malloc 的指针永远不会被释放。我已经验证关联的图像对象最终被释放,而不是提供者的分配。我应该显式创建一个数据提供程序并以某种方式管理它的内存吗?看起来像黑客。
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, blah blah blah);
CGColorSpaceRelease(colorSpace);
// ... draw into context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage * image = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);
CGContextRelease(context);
在下面的 fbrereto 回答之后,我将代码更改为:
- (UIImage *)modifiedImage {
CGSize size = CGSizeMake(width, height);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// draw into context
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image; // image retainCount = 1
}
// caller:
{
UIImage * image = [self modifiedImage];
_imageView.image = image; // image retainCount = 2
}
// after caller done, image retainCount = 1, autoreleased object lost its scope
不幸的是,这仍然表现出相同的问题,并具有水平翻转图像的副作用。它似乎在内部对 CGBitmapContextCreateImage 做了同样的事情。
我已经验证了我的对象的 dealloc
被调用。在我释放_imageView
之前,_imageView.image
和_imageView
上的retainCount都是1。这确实没有道理。其他人似乎也有这个问题,我是最后一个怀疑 SDK 的人,但是这里是否存在 iPhone SDK 错误???
Like in this post:
I'm having a similar problem. The pointer from the malloc in create_bitmap_data_provider
is never freed. I've verified that the associated image object is eventually released, just not the provider's allocation. Should I explicitly create a data provider and somehow manage it's memory? Seems like a hack.
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, blah blah blah);
CGColorSpaceRelease(colorSpace);
// ... draw into context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage * image = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);
CGContextRelease(context);
After fbrereto's answer below, I changed the code to this:
- (UIImage *)modifiedImage {
CGSize size = CGSizeMake(width, height);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// draw into context
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image; // image retainCount = 1
}
// caller:
{
UIImage * image = [self modifiedImage];
_imageView.image = image; // image retainCount = 2
}
// after caller done, image retainCount = 1, autoreleased object lost its scope
Unfortunately, this still exhibits the same issue with a side effect of flipping the image horizontally. It appears to do the same thing with CGBitmapContextCreateImage internally.
I have verified my object's dealloc
is called. The retainCount on the _imageView.image
and the _imageView
are both 1 before I release the _imageView
. This really doesn't make sense. Others seem to have this issue as well, I'm the last one to suspect the SDK, but could there be an iPhone SDK bug here???
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
看起来问题在于您正在释放指向返回的 CGImage 的指针,而不是 CGImage 本身。我之前也遇到过类似的问题,分配量不断增加,最终应用程序崩溃。我通过分配 CGImage 而不是 CGImageRef 来解决这个问题。更改后,在带有分配的 Instruments 中运行代码,您应该不会再看到 malloc 的永久内存消耗。同样,如果您使用类方法
imageWithCGImage
,您将不必担心稍后自动释放您的UIImage
。我在 PC 上输入了此内容,因此如果您将其直接放入 XCode 中,您可能会遇到语法问题,我提前表示歉意;然而校长是健全的。
It looks like the problem is that you are releasing a pointer to the returned
CGImage
, rather than theCGImage
itself. I too was having similar issues before with continual growing allocations and an eventual app crash. I addressed it by allocating aCGImage
rather than aCGImageRef
. After the changes run your code in Insturments with allocations, and you should not see anymore perpetual memory consumption from malloc. As well if you use the class methodimageWithCGImage
you will not have to worry about autoreleasing yourUIImage
later on.I typed this on a PC so if you drop it right into XCode you may have syntax issue, I appologize in advance; however the principal is sound.
我遇到了这个问题,这让我抓狂了几天。经过大量挖掘并注意到使用 Instruments 的 CG 栅格数据泄漏。
问题似乎出在 CoreGraphics 内部。我的问题是,当我在紧密循环中使用 CGBitmapContextCreateImage 时,它会在一段时间内保留一些图像(每个 800kb),并且会慢慢泄漏。
经过几天的 Instruments 跟踪后,我发现一个解决方法是使用 CGDataProviderCreateWithData 方法。有趣的是,输出是相同的 CGImageRef,但这次 Core Graphics 在 VM 中不会使用 CG 光栅数据,也不会泄漏。我假设这是一个内部问题或滥用它。
这是拯救我的代码:
关键是在下面的方法中使用 CGDataProviderCreateWithData 。
I had this problem and it drove me nuts for a few days. After much digging and noticing a leak in CG Raster Data using Instruments.
The problem seems to lie inside CoreGraphics. My problem was when i was using CGBitmapContextCreateImage in a tight loop it would over a period of time retain some images (800kb each) and this slowly leaked out.
After a few days of tracing with Instruments I found a workaround was to use CGDataProviderCreateWithData method instead. The interesting thing was the output was the same CGImageRef but this time there would be no CG Raster Data used in VM by Core graphics and no leak. Im assuming this is an internal problem or were misusing it.
Here is the code that saved me:
The key was using CGDataProviderCreateWithData in the method below.
我建议您不要手动创建 CGContextRef,而是利用
UIGraphicsBeginImageContext
,如 这篇文章。有关这组例程的更多详细信息,请参阅 在这里。我相信这将有助于解决这个问题,或者至少让您减少管理自己的记忆。更新:
根据新代码,从函数中出来的
UIImage
的retainCount
将为 1,将其分配给 imageView 的图像将导致它碰撞到2. 此时,释放 imageView 将使UIImage
的retainCount
为 1,从而导致泄漏。因此,在将UIImage
分配给 imageView 后,release
它很重要。它可能看起来有点奇怪,但它会导致retainCount
被正确设置为 1。Instead of manually creating your CGContextRef I'd suggest you leverage
UIGraphicsBeginImageContext
as demonstrated in this post. More details on that set of routines can be found here. I trust it'll help to resolve this issue, or at the very least give you less memory you have to manage yourself.UPDATE:
Given the new code, the
retainCount
of theUIImage
as it comes out of the function will be 1, and assigning it to the imageView's image will cause it to bump to 2. At that point deallocating the imageView will leave theretainCount
of theUIImage
to be 1, resulting in a leak. It is important, then, after assigning theUIImage
to the imageView, torelease
it. It may look a bit strange, but it will cause theretainCount
to be properly set to 1.您不是唯一遇到此问题的人。我在 CGBitmapContextCreateImage() 方面遇到了重大问题。当您打开“僵尸”模式时,它甚至会警告您内存被释放两次(当情况并非如此时)。将 CG* 内容与 UI* 内容混合时肯定会出现问题。我仍在尝试找出如何解决这个问题的代码。
旁注:调用 UIGraphicsBeginImageContext 不是线程安全的。当心。
You're not the only one with this problem. I've had major problems with CGBitmapContextCreateImage(). When you turn on Zombie mode, it even warns you that memory is released twice (when it's not the case). There's definitely a problem when mixing CG* stuff with UI* stuff. I'm still trying to figure out how to code around this issue.
Side note: calling UIGraphicsBeginImageContext is not thread-safe. Be careful.
这真的对我有帮助!以下是我如何使用它来修复令人讨厌的泄漏问题:
注意,我必须将 CFDataRef (对于 CFRelease(image->imageRef))存储在我的 ~Image 函数中。希望这也能帮助其他人...JR
This really helped me! Here's how I used it to fix that nasty leak problem:
Notice, I had to store the CFDataRef (for a CFRelease(image->imageRef)) in my ~Image function. Hopefully this also helps others...JR