1

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.

Community
  • 1
  • 1
pAK-76
  • 305
  • 3
  • 8
  • ARC has no bearing on Quartz types because they are Core Foundation types, not Objective-C classes/objects. ARC only handles retain/release for Objective-C classes. – Jonathan Grynspan Jan 24 '13 at 11:59
  • Jonathan, I know it. This is why I release image using CGImageRelease. The problem is if I release - it crushes. If I don't - it leaks. – pAK-76 Jan 24 '13 at 12:43

2 Answers2

1

This is pretty old, but I had the same problem in my case. The issue was releasing colorspace without actually having a copy of it. CGImageGetColorSpace(cropped) gives you a pointer to existing color space and you should not release it. It's not a copy created for you. That was my case. When I noticed that (I used code from the internet to scale image as well) CGDisplayCreateImage(displays[0]) was not crashing anymore.

dobry
  • 131
  • 1
  • 7
0

Actually, I got rid of this leak by using Core Graphics only if necessary, i.e. after grabbing the screen I wrap it into NSImage*, and atter I work only with it. But it is still interesting, what was wrong with the code above.

pAK-76
  • 305
  • 3
  • 8