Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CGImageRef Memory leak

I'm having a memory leak when using this custom method which returns a CGImageRef. I can't release "cgImage" properly because I have to return it. What chould I do ?

- (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;     
}
like image 992
Louis de Decker Avatar asked Dec 31 '10 01:12

Louis de Decker


3 Answers

cgImage is owned by your method, you need to return it and give responsibility to the caller to release it through CFRelease.

You can also return the CGImage wrapped inside a UIImage instance, like this:

UIImage *image = [UIImage imageWithCGImage:cgImage];
CFRelease(cgImage); //cgImage is retained by the UIImage above
return image;
like image 132
Jacob Relkin Avatar answered Nov 18 '22 11:11

Jacob Relkin


This is a general problem with Core Foundation objects because there is no autorelease pool in CF. As I see it, you have two options to solve the problem:

  1. Rename the method to something like -newRectRoundedImageRef:radius: to tell the caller that he takes ownership of the returned object and responsible for releasing it.
  2. Wrap the CGImageRef in an autoreleased UIImage object and return that ([UIImage imageWithCGImage:]). That's probably what I would do.
like image 11
Ole Begemann Avatar answered Nov 18 '22 10:11

Ole Begemann


You can autorelease a Core Foundation-compatible object. it just looks a bit wonky. :)

The GC-safe way is like so:

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

The shortcut, which is safe on iOS but no longer safe on the Mac, is this:

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

Either one will place the image in an autorelease pool and prevent a leak.

like image 3
Jonathan Grynspan Avatar answered Nov 18 '22 11:11

Jonathan Grynspan