I am getting a static analyzer warning about some CGImageRef objects. The warning is "Incorrect decrement of the reference count of an object that is not owned at this point by the caller." However, I want it to be owned by the caller. Is there some special wording I need to insert into my Obj-C method? When I make a C function to do literally line for line the exact same thing, the warning disappears. The reason I separate them is because sometimes my app uses the CGImage (for editing), and sometimes it uses a UIImage (for setting a UIImageView).
Here is the relevant code (stripped down to its relevant essentials):
+ (UIImage *)imageFromCompressedData:(NSData *)compressedData withSize:(CGSize)size
{
CGImageRef cgImage = [SO2CompressionHandler cgImageFromCompressedData:compressedData withSize:size];
UIImage *returnImage = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
return returnImage;
}
+ (CGImageRef)cgImageFromCompressedData:(NSData *)compressedData withSize:(CGSize)size
{
//...decompress data
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)decodedData);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef outImageRef = CGImageCreate(width, height, 8, 32, 4*width, colorSpace, kCGImageAlphaPremultipliedLast, provider, NULL, false, kCGRenderingIntentDefault);
CGDataProviderRelease(provider);
if(CGSizeEqualToSize(CGSizeZero, size) || CGSizeEqualToSize(CGSizeMake(width, height), size))
{
CGColorSpaceRelease(colorSpace);
return outImageRef; //Flagged as potential leak
}
//...or resize and return the in a similar way
}
It doesn't make sense to release the CGImage before I return it right? Then it would just be invalid memory. So is this a hint that I should be using C-functions? Or does the static analyzer simply not check C-functions. I changed cgImageFromCompressedData:withSize:
into CGImageCreateWithCompressedData(NSData *compressedData, CGSize size)
and like magic, no more warnings. Should I just ignore the warnings, or do they have some merit? Do I have to add the word "new" or "alloc" to my Obj-C method name to make them go away?
If your method returns a +1 object, its name should start with 'new', e.g. newCGImageFromCompressedData:withSize:
. This will tell the analyzer that you are deliberately returning a retained object and passing ownership to the caller.
Alternatively, you can make use of the clang attribute CF_RETURNS_RETAINED
by putting this in your method declaration (i.e. in your .h file):
+(CGImageRef)cgImageFromCompressedData:(NSData *)compressedData
withSize:(CGSize)size CF_RETURNS_RETAINED;
This also tells the analyzer that the method is supposed to returned a retained object, but without having to change the method selector.