【问题标题】:Crash caused by calling CFRelease() in iOS app在 iOS 应用中调用 CFRelease() 导致的崩溃
【发布时间】:2017-03-14 06:02:34
【问题描述】:

我是 iOS 和 objc 的新手。我写了一个方法,它给了我来自 UTI 的标签类 (mime type, file extension etc) -

- (NSString *)tagForClass:(CFStringRef)tagClass forUTI:(NSString *)UTI {
    CFStringRef UTIRef = (__bridge CFStringRef)(UTI);
    CFStringRef tagRef = UTTypeCopyPreferredTagWithClass(UTIRef, tagClass);
    NSString *tag = (NSString *)CFBridgingRelease(tagRef);
    CFRelease(tagRef);
    return tag;
}

此方法在CFRelease(tagRef); 行上因EXC_BAD_ACCESS 而崩溃。使用Zombies 进行分析告诉我“Objective-C 消息已发送到地址为 0x60800023f640 的已释放 'CFString (immutable)' 对象 (zombie)。”

我的理解是,我拥有tagRef,因为返回该对象的方法中包含“复制”一词。所以,我应该在完成后打电话给CFRelease()

如果我删除 CFRelease() 行,程序运行良好。但是我担心在这种情况下会导致内存泄漏。

任何帮助将不胜感激!

【问题讨论】:

  • This 会帮助你。
  • 好的。在该链接中接受的答案中,rmaddy 说没有必要释放extension 对象,因为它是通过__bridge_transfer 投射转移到ARC 的。那么CF对象extension和objc对象ext是堆上的同一个对象吗?
  • 我刚刚验证了这一点。在我发布的我自己的代码中,tagReftag 是堆上的相同对象(它们具有相同的内存地址)。所以调用CFRelease(tagRef) 是在释放这个堆对象,然后我通过return tag 返回一个指向这个释放对象的指针,这导致了崩溃。通过删除 CFRelease() 调用修复。
  • 是的,因为 tagRef 已转移到 ARC,并被释放了两次,删除 CFRelease() 应该是解决方法。

标签: ios objective-c memory-management memory-leaks


【解决方案1】:

Core Foundation 中的约定是,当函数名包含CopyCreate 时,它返回一个保留计数为+1 的对象。处理完对象后,必须在其上调用释放函数来平衡 +1。

当您致电CFBridgingRelease(tagRef) 时,会平衡 +1。这就是函数名称中包含 Release 的原因。所以你也不应该在对象上调用CFRelease。这是正确的代码:

- (NSString *)tagForClass:(CFStringRef)tagClass forUTI:(NSString *)UTI {
    CFStringRef UTIRef = (__bridge CFStringRef)(UTI);
    CFStringRef tagRef = UTTypeCopyPreferredTagWithClass(UTIRef, tagClass);
    // You are now responsible for one release of tagRef.

    NSString *tag = (NSString *)CFBridgingRelease(tagRef);
    // You have now performed one release of tagRef.

    return tag;
}

【讨论】:

    【解决方案2】:

    我认为,如果您在已经取消整理的Object 上执行CFRelease() 或引用计数为0Object,那么Object 引用计数已经是0。所以你不能发布可能有问题的Object

    尝试使用以下语句打印Object 引用计数,以便您了解。

    NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));
    

    此外,如果您使用 ARC,则无需管理 Object 引用计数。它将由ARC管理。

    【讨论】:

    • 我虽然使用 ARC 的全部意义在于不必考虑引用计数:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多