Jacksonkr
Jacksonkr

Reputation: 32247

ios thwarting a potential memory leak

- (NSString*)encodeURL:(NSString *)string
{
    NSString *newString = (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));

    if (newString) 
    {
        return newString; // <-- potential leak here
    }

    return @"";
}

I'm not familiar with CFTypes (other than knowing what they are). This is code I got from the internet and have had to finagle a bit to get it to work in ARC. I'm getting a potential leak warning and I'm not sure how to fix it. Suggestions?

Upvotes: 2

Views: 1209

Answers (3)

Harrison Xi
Harrison Xi

Reputation: 796

Another way is using __bridge_transfer instead of __bridge like this:

NSString *newString = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));

See more informations in this question: Correct bridging for ARC?

Upvotes: 0

Rob Napier
Rob Napier

Reputation: 299683

Yes, this is a memory leak. You meant to use CFBridgingRelease() rather than __bridge.

The object created by CFURLCreateStringByAddingPercentEscapes has an extra retain on it because it includes Create. You need to transfer that object to ARC, letting it know to add an extra release, that's what CFBridgingRelease() does.

NSString *newString = 
    CFBridgingRelease(
        CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, 
                                               (__bridge CFStringRef)string, 
                                               NULL,
                                               CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"),           
                                               kCFStringEncodingUTF8));

You do use __bridge for the passed-in string because you're not transferring it to Core Foundation. You're just asking Core Foundation to use it while ARC continues to own it. When you "transfer" ownership, you generally mean "this object used to be Core Foundation, and now it's ARC" (or vice versa). That's what's happening to newString.

I swapped the long NS-to-CF encoding function with the result just to make it shorter.

Upvotes: 8

JustSid
JustSid

Reputation: 25328

return a autoreleased version of the string, CFStringRef can be converted to NSString and vice versa, which also means that you can treat it like a normal NSString and thus autorelease it (if you are interested in this you should read about the toll free bridging between parts of Foundation and Core Foundation)

Upvotes: 0

Related Questions