Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper memory management with CFStringRef and CFRelease

Consider this simple method; it's a category on NSString.

- (NSString *)stringByUrlEncoding
{
    CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", kCFStringEncodingUTF8);
    NSString *returnString = (__bridge NSString *)newString;
    CFRelease(newString);
    return returnString;
}

Its job is to turn = into %3D, etc. for URL encoding, but that's not relevant to this question.

A few questions about memory management:

  1. After CFRelease(newString); is called, I can still po newString in the debugger and see the string. Does this mean it's not getting deallocated properly?

  2. When I pass casted CFStringRefs to arguments of CFURLCreateStringByAddingPercentEscapes, (like (CFStringRef)self, for example) I believe that I do NOT need to store those to a variable and then CFRelease them due to "toll-free bridging". Is this correct?

  3. Does the answer to #2 change if it's a CGImageRef, not a CFStringRef? Why does CGImageRef have its own CGImageRelease function, but there's no CFStringRelease method?

  4. To make sure my understanding of __bridge_transfer is correct, is this modified code identical?

    - (NSString *)stringByUrlEncoding
    {
        CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", kCFStringEncodingUTF8);
        NSString *returnString = (__bridge_transfer NSString *)newString;
        // CFRelease(newString);
        return returnString;
    }
    
like image 342
Aaron Brager Avatar asked Feb 19 '13 19:02

Aaron Brager


1 Answers

As to your questions:

1) You don't have enough information to know if newString should have been deallocated. For instance, if no character replacement was actually needed, it would be reasonable for CFURLCreateStringByAddingPercentEscapes to return you the equivalent of [self retain]; This is but one example. The broader point is "you can't know." The normal approach here would be to use Instruments to look for heap growth and leaks. For more information, google "retainCount useless" (I won't rehash it here.)

2) Yes.

3) CGImageRef is not toll-free bridged, however, as I understand it, CFRetain and CFRelease should work. The difference between CFRelease and CGImageRelease here is that the parameter to CFRelease must not be NULL, whereas CGImageRelease will tolerate NULL parameters.

4) __bridge_transfer is the appropriate annotation to use here. This "transfers" the +1 retain count from the side that ARC doesn't handle to the side it does handle. Put differently, __bridge_transfer just tells ARC that it will need to create a release call for this pointer, even through it never generated a retain.

like image 150
ipmcc Avatar answered Sep 17 '22 14:09

ipmcc