【问题标题】:CGImageRef Memory leakCGImageRef 内存泄漏
【发布时间】:2011-06-01 20:01:19
【问题描述】:

我在使用这个返回 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;     
}

【问题讨论】:

标签: objective-c memory-management quartz-graphics


【解决方案1】:

cgImage 归你的方法所有,你需要返回它并让调用者负责通过CFRelease 释放它。

您还可以返回包裹在UIImage 实例中的CGImage,如下所示:

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

【讨论】:

  • 这个答案不再相关:“CFRelease”不可用:Core Foundation 对象自动进行内存管理
【解决方案2】:

这是 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];
    }
    

    任何一个都会将图像放入自动释放池中并防止泄漏。

    【讨论】:

      【解决方案4】:

      按照建议,我们使用了:

      CGImageRelease(imageRef);
      

      但我们仍然有内存泄漏。 我们的解决方案是用

      包装代码
      @autoreleasepool {}
      

      阻止,这解决了我们的问题。

      【讨论】:

      • 仍然没有正确释放它 tbh
      猜你喜欢
      • 1970-01-01
      • 2023-03-23
      • 2015-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-08
      • 2013-01-20
      相关资源
      最近更新 更多