When running the Clang Static Analyzer against code that I've converted to use ARC, it's reporting the NSNumber in this block of code to be a leak:
NSNumber *temporaryNumber = [NSNumber numberWithFloat:0.85];
CFNumberRef compressionQuality = CFBridgingRetain(temporaryNumber);
CFDictionarySetValue(snapshotMetaAndOpts, kCGImageDestinationLossyCompressionQuality, compressionQuality);
CFRelease(compressionQuality);
The analyzer indicates that the NSNumber created and stored into temporaryNumber ends up with a +1 retain count after all this, and thus leaks. I know that I could just as easily do
CFDictionarySetValue(snapshotMetaAndOpts, kCGImageDestinationLossyCompressionQuality, (__bridge CFNumberRef)[NSNumber numberWithFloat:0.85]);
but I'm still trying to understand the exact actions of bridging in ARC, so I'm trying to puzzle out the above. The actual analyzer output is as follows:
The way I read CFBridgingRetain()
and __bridge_retained
is that they transfer ownership of an ARC-managed NSObject to Core Foundation by increasing the retain count by 1. I balance this with a corresponding CFRelease()
. I would the expect the NSNumber to be created as an autoreleased object, and therefore be completely balanced on the ARC side.
Similarly, if I do the following using a plain __bridge
cast:
NSNumber *temporaryNumber = [NSNumber numberWithFloat:0.85];
CFNumberRef compressionQuality = (__bridge CFNumberRef)temporaryNumber;
CFDictionarySetValue(snapshotMetaAndOpts, kCGImageDestinationLossyCompressionQuality, compressionQuality);
CFRelease(compressionQuality);
the static analyzer gives this a clean bill of health.
Am I misreading something in the way that objects are toll-free bridged, or is this a bug in the static analyzer?
EDIT: This is an analyzer bug. I have the latest build of the standalone analyzer on my machine and there is no warning. I verified against a build with the current shipping analyzer and got the same results as you. Looks like its already good to go.
What version of Xcode are you using? I just tested the following.
int main(int argc, char *argv[])
{
@autoreleasepool
{
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
NSNumber *temporaryNumber = [NSNumber numberWithFloat:0.85];
CFNumberRef compressionQuality = CFBridgingRetain(temporaryNumber);
CFDictionarySetValue(dict, CFSTR("Test"), compressionQuality);
CFRelease(compressionQuality);
CFRelease(dict);
}
}
This works as expected and provides no analyzer warnings. This is on the latest 4.2 on 10.7, using the iOS SDK.