I have the memory leak problem with CGImageRef (I guess, it's so) in my Cocoa Desktop Application. I've read lots of questions here and anywhere else, read FAQ of Core Graphics memory management on developer.apple.com. Maybe this question is more similar to mine, though solution didn't help.
My task is to scale area 15*15 from saved CGImage and return NSImage* as a result, it is done on each mouse movement.
-(NSImage*)getScaledAreaInX:(int)x andY:(int)y
{
// Catching image from the screen
CGImageRef fullscreen = CGImageRetain(_magniHack);
// Cropping
int screenHeight = CGImageGetHeight(fullscreen);
CGRect fixedRect = CGRectMake(x-7, screenHeight-y-8, 15, 15);
CGImageRef cropped = CGImageCreateWithImageInRect(fullscreen, fixedRect);
// Scaling
int width = CGImageGetWidth(cropped)*8; // New width;
int height = CGImageGetHeight(cropped)*8; // New height;
CGColorSpaceRef colorspace = CGImageGetColorSpace(cropped);
CGContextRef context = CGBitmapContextCreate(NULL, width, height,
CGImageGetBitsPerComponent(cropped),
CGImageGetBytesPerRow(cropped),
colorspace,
CGImageGetAlphaInfo(cropped));
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), cropped);
CGImageRef scaled = CGBitmapContextCreateImage(context);
// Casting to NSImage
NSImage *image = [[NSImage alloc] initWithCGImage:scaled size:NSZeroSize];
// Releasing memory
CGImageRelease(fullscreen);
CGColorSpaceRelease(colorspace);
CGContextRelease(context);
//CGImageRelease(cropped); // Can't do: will crash; In what situations can free?
cropped = NULL;
CGImageRelease(scaled);
scaled = NULL;
return image;
}
If I uncomment CGImageRelease line, app will crash on 6th movement of cursor, on retaining _magniHack or cropping the image (it differs every time), the message is "EXC_BAD_ACCESS". If I don't, there will be memory leak every time (during frequent movements the leak is dozens of MB). The same result I get if I release cropped, but do not release scaled image (though leak will be much more).
_magniHack - CGImageRef, it is private instance variable, it is set only once in that code:
-(void)storeFullScreen
{
if (_magniHack) {
CGImageRelease(_magniHack);
}
_magniHack = CGDisplayCreateImage(displays[0]);
}
I use ARC in project if it helps. Though this thing still can't help get rid of leaks. I guess that _magniHack is released somewhere, but I can't find, where, cause I always implement retain on start and release in the end.