【问题标题】:Obj-C, Reference-counted object is used after it is released?Obj-C,引用计数的对象释放后使用?
【发布时间】:2012-03-25 21:41:47
【问题描述】:

我收到以下警告。

引用计数对象释放后使用

为此文件启用了 ARC。

我尚未将我的应用转换为使用 ARC,并且目前对它没有正确的理解。但是,乍一看我很困惑为什么这段代码会有问题(它来自库),我的意思是我知道这里不应该使用 autorelease?

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    id uuid = [defaults objectForKey:@"uniqueID"];
    if (uuid)
        uniqueID = (NSString *)uuid;
    else {
        CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
        uniqueID = (__bridge NSString *)cfUuid;
        CFRelease(cfUuid);
        [defaults setObject:uniqueID forKey:@"uniqueID"]; // warning here
    }

编辑 @JohnCalsbeek,@epatel,@Chuck 谢谢,我刚刚尝试过,我在CFStringRef cfUuid 行收到了一个新警告,说可能存在泄漏。

这是完整的文件https://github.com/MugunthKumar/MKStoreKit/blob/master/MKSKProduct.m

【问题讨论】:

    标签: iphone objective-c ios cocoa-touch


    【解决方案1】:

    试试这个,求小姐姐理解哈哈

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    id uuid = [defaults objectForKey:@"uniqueID"];
    
    if (uuid)
        uniqueID = [NSString stringWithString:(NSString *)uuid];
    else {
        CFUUIDRef temp = CFUUIDCreate(NULL);
        CFStringRef cfUuid = CFUUIDCreateString(NULL, temp);
        uniqueID = [NSString stringWithString:(__bridge NSString*) cfUuid];
        CFRelease(cfUuid);
        CFRelease(temp);
    
        [defaults setObject:uniqueID forKey:@"uniqueID"]; // warning here
    }
    

    【讨论】:

    • @Jules 实际上我刚刚意识到这是一个 CCFUID 标识符,让我编辑我的答案。
    • @Jules 忘了告诉你,使用 clang 静态分析器,这变得非常容易理解。 (你可以在你的项目调试选项中打开它)
    • 感谢@LuisOscar 已修复,如果只有少数文件使用 ARC,我可以打开 clang 静态分析器吗?
    • 说实话我不知道,因为我开始将它与 arc 一起使用。试一试,如果你遇到太多奇怪的错误,你可以把它关掉哈哈。祝你好运
    【解决方案2】:

    __bridge 演员表不是所有权转让。 uniqueID 不会成为拥有引用,因此在带有警告的行中变得无效。您可以使用__bridge_transfer(将所有权转移到Objective-C 引用)并删除您的CFRelease 调用,或者将调用更改为CFRelease 以在调用-setObject:forKey: 之后。

    【讨论】:

    • 你试过__bridge_transfer 版本吗?
    【解决方案3】:

    我相信可能是这条线没有达到你的预期

    uniqueID = (__bridge NSString *)cfUuid;
    

    这是一个简单的转换,下一行实际上将释放cfUuiduniqueID(实际上是同一个对象)。

    所以我会将以下几行的顺序更改为

    [defaults setObject:uniqueID forKey:@"uniqueID"]; // warning here
    CFRelease(cfUuid);
    

    【讨论】:

      【解决方案4】:

      您使用CFUUIDCreateString(NULL, CFUUIDCreate(NULL) 创建一个字符串。然后你分配uniqueID 来引用那个字符串。然后用CFRelease(cfUuid) 释放字符串。然后在下一行使用字符串(如uniqueID)。那是无效的,因为你刚刚发布了它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-13
        相关资源
        最近更新 更多