CGImageRef 内存泄漏

7

当使用这个自定义方法返回CGImageRef时,我遇到了内存泄漏的问题。由于必须返回cgImage,所以我无法正确释放它。我该怎么办?

- (CGImageRef)rectRoundedImageRef:(CGRect)rect radius:(int)radius
{
    CGSize contextSize = CGSizeMake(rect.size.width, rect.size.height);     
    CGFloat imageScale = (CGFloat)1.0;
    CGFloat width = contextSize.width;
    CGFloat height = contextSize.height;        
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, width * imageScale, height * imageScale, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
    // Draw ...
    // Get your image
    CGImageRef cgImage = CGBitmapContextCreateImage(context);       
    CGColorSpaceRelease(colorSpace);
    CGContextRelease(context);
    //CGImageRelease(cgImage); //If I release cgImage the app crashes.
    return cgImage;     
}

我有类似的泄漏问题。请查看我的答案:https://dev59.com/tUnSa4cB1Zd3GeqPNWKv#23669476 - Vlad
4个回答

16

cgImage 由您的方法持有,您需要返回它并将释放责任交给调用者通过 CFRelease

您还可以像这样返回包装在 UIImage 实例中的 CGImage

UIImage *image = [UIImage imageWithCGImage:cgImage];
CFRelease(cgImage); //cgImage is retained by the UIImage above
return image;

此答案不再相关:'CFRelease' 不可用:核心基础框架对象自动进行内存管理。 - Mycroft Canner

11

这是Core Foundation对象的一般问题,因为在CF中没有自动释放池。据我所见,您有两种解决问题的选择:

  1. 将方法重命名为-newRectRoundedImageRef:radius:之类的名称,以告诉调用者他获取了返回对象的所有权,并负责释放它。
  2. CGImageRef封装在一个自动释放的UIImage对象中并返回它([UIImage imageWithCGImage:])。这可能是我会做的事情。

3
您可以自动释放与 Core Foundation 兼容的对象。只是看起来有点奇怪。 :)
GC 安全的方式如下:
CGImageRef image = ...;
if (image) {
    image = (CGImageRef)[[(id)image retain] autorelease];
    CGImageRelease(image);
}

这个快捷方式在iOS上是安全的,但在Mac上不再安全。具体内容如下:

该快捷方式指的是:

CGImageRef image = ...;
if (image) {
    image = (CGImageRef)[(id)image autorelease];
}

无论哪种方法都会将图像放入自动释放池并防止泄漏。

3

根据建议,我们使用了:

CGImageRelease(imageRef);

但是我们仍然存在内存泄漏的问题。 我们的解决方案是用一个闭合的

标签来包裹代码。
@autoreleasepool {}

使用块级元素可以解决我们的问题。


实话实说,它仍然没有正确地释放。 - Reza.Ab

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