在iOS应用程序中调用CFRelease()导致崩溃

时间:2017-03-14 06:02:34

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

我是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;
}

此方法在EXC_BAD_ACCESS行上与CFRelease(tagRef);崩溃。使用Zombies进行分析告诉我,“Objective-C消息已发送到已解除分配的”CFString (immutable)“对象(zombie),地址为:0x60800023f640。”< / p>

我理解这一点的方式是,我拥有tagRef作为返回该对象的方法,其中包含“copy”一词。所以,我应该在完成后调用CFRelease()

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

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:0)

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;
}

答案 1 :(得分:-1)

我认为,如果你的CFRelease()已取消ObjectObject且引用次数为0,那么Object引用次数已经0 1}}。因此,您无法释放可能存在问题的Object

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

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

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