【问题标题】:Releasing Core Foundation object references释放核心基础对象引用
【发布时间】:2009-05-15 18:47:39
【问题描述】:

我需要释放一个核心基础对象来清理内存吗?如果有,怎么做?

例如在代码中:

ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);

我需要释放peopleArray吗? addressBook 呢?

【问题讨论】:

    标签: objective-c cocoa cocoa-touch core-foundation


    【解决方案1】:

    是的,在 CoreFoundation 中,您必须发布名称中带有 Create 或 Copy 的任何内容。您可以使用 CFRelease() 执行此操作。在您的情况下,您应该同时释放数组和地址簿引用。

    【讨论】:

    • 谢谢。我很难在谷歌上找到这个问题的答案。可能是因为我在谷歌上搜索“核心框架”而不是“核心基础”。嗬! :)
    【解决方案2】:

    Core Foundation 中用于内存管理的 rules 与 Cocoa 中的类似:如果返回引用的方法包含“创建”或“复制”字样,则您拥有该引用,并且必须调用 CFRelease()参考放弃所有权。否则,您确实拥有该引用,并且必须调用CFRetain 来获取所有权(必然需要随后的CFRelease 来放弃该新所有权)。这些规则取自 Core Foundation 的内存管理编程指南:

    • 如果您创建一个对象(无论是 直接或通过复制 另一个对象——参见“创建 规则”),你拥有它。
    • 如果你得到一个 来自其他地方的对象,你做 不拥有它。如果你想阻止它 被处置,您必须添加 自己作为所有者(使用 CF 保留)。
    • 如果您是 反对,您必须放弃所有权 当你用完它 (使用 CFRelease)。

    在您的示例中,addressBookpeopleArray 都必须被释放。由于 Core Foundation 中没有 autorelease 等效项,因此如果您从方法返回引用,则返回数组而不释放它。您应该(除非您是邪恶的)然后在方法名称中包含“create”,以向调用者表明他们现在拥有对返回对象的引用。在这种情况下,CFArray 被免费桥接到NSCFArray,这是一个继承自NSObject 的Objective-C 对象。因此,如果您需要从函数/方法返回它,您可以将 peopleArray 转换为 NSArray*autorelease

    return [(NSArray*)peopleArray autorelease];
    

    请注意,这仅适用于免费桥接课程。我的理解是,制作自己的免费桥接类相当困难,并且只有原始(字符串、数组等)CF 类是免费桥接的,因此这种方法并不总是有效。最后,如果您可以避免使用autorelease(即您可以使您的内存管理更加明确),那可能总是一件好事。

    【讨论】:

    • 谢谢 Barry - 我精通 Cocoa 的内存规则 - 我只是不确定 CF 规则是否相同。很高兴知道他们是。
    • 一样,除了缺少自动释放...如果您对 Cocoa 规则感到满意并尽可能避免自动释放,那么您就完全没有问题了。
    • 免费桥接的对象可以通过转换为 id 自动释放:[(id)cfObject autorelease];
    • 对,所以在这种情况下,CFArrayRef 可以转换为 NSArray* 并自动释放,如 [(NSArray*)peopleArray autorelease]。我会将其添加到答案文本中。
    • 那么如何返回不是免费桥接的对象?
    【解决方案3】:

    还有一个没有人提到的小问题,一些 CF 课程与他们的 NS 课程有“免费桥梁”。 CFStringNSStringCFArrayNSArray 都是示例。这是相关的,因为您可以将 release 与这些类一起使用。

    请参阅此other StackOverflow question 了解更多信息。

    【讨论】:

      【解决方案4】:

      我建议阅读 Apple 关于 Core Foundation 内存管理的 guide,以深入讨论这一点。他们也有类似的通用 Cocoa 内存管理指南。

      要释放 CF 对象,您可以调用 CFRelease 函数。

      【讨论】:

        【解决方案5】:

        对于 ARC,您可以使用。

        return (__bridge_transfer NSArray*)peopleArray;
        

        "__bridge_transfer" 会将所有权转移给 ARC,因此您不需要任何进一步的发布调用。

        【讨论】:

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