4

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:

Visual depiction of static analyzer results

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?

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
  • This is an analyzer bug in Xcode 4.2, as Joshua points out below, and it appears to have been fixed with the version of the analyzer shipping with Xcode 4.3. – Brad Larson Mar 11 '12 at 19:10

1 Answers1

5

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.

Joshua Weinberg
  • 28,598
  • 2
  • 97
  • 90
  • Xcode 4.2, build 4D199. I've updated the question with an image showing the static analyzer results for this block of code. For kicks, I tried wrapping my above code in an explicit `@autoreleasepool` to see if that made any difference, but it didn't. – Brad Larson Oct 31 '11 at 19:02
  • Edited my answer based on the new info. Looks like it was just the analyzer not playing nice with ARC, I'd recommend grabbing the latest analyzer build. Its easy to drop in and replace the one inside of Xcode. http://clang-analyzer.llvm.org/xcode.html – Joshua Weinberg Oct 31 '11 at 19:06
  • I was just about to comment about trying your sample and having it fail in the same way. If they've already fixed it in the Clang project, do you think there's any point in filing a bug report? – Brad Larson Oct 31 '11 at 19:10
  • Probably not, unless you see it pop up again after updating. – Joshua Weinberg Oct 31 '11 at 19:10
  • 1
    Cool. Thanks for the help in tracking this down and making me feel a little less crazy. – Brad Larson Oct 31 '11 at 19:13