简体   繁体   中英

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?

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.

返回一个自动释放的字符串版本, CFStringRef可以转换为NSString ,反之亦然,这也意味着你可以像普通的NSString一样对待它,从而自动释放它(如果你对此感兴趣,你应该阅读有关之间的免费桥接FoundationCore Foundation

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM