6

我想知道处理在内存管理代码中对象不属于任何特定所有者的情况的推荐方法是什么,即对象自己释放。一个这样的例子可能是 NSWindowController 的子类,它配置、显示和管理单个窗口的输入和输出。控制器对象显示一个窗口并稍后在某个时候释放自己(通常在它管理的窗口或工作表关闭时)。AppKit 也提供了几个例子: NSAnimation 在 startAnimation 中保留自己并在动画完成时释放自己。另一个例子是 NSWindow,它可以配置为在关闭时释放自己。

在自己实现这些“自有”对象时,我看到至少三种不同的 GC 安全模式,但它们都有一些缺点。

一种)。使用 CFRetain/CFRelease。

自有对象在开始其操作之前调用自身的 CFRetain(例如,在窗口控制器示例中,在窗口显示之前)。然后它在完成后调用自身的 CFRelease()(例如,在窗口关闭后的窗口控制器示例中)。

优点:对象的用户不必担心内存管理。
缺点:有点难看,因为需要使用内存管理功能,尽管我们在纯 ObjC 代码中使用 GC。如果没有调用 CFRelease(),泄漏可能很难定位。

乙)。避免使用静态数据结构的自我所有权习语。

对象在开始操作之前将自己添加到数据结构(例如静态可变数组)中,并在完成后将自己从那里移除。

优点:对象的用户不必担心内存管理。不调用内存管理函数。对象有明确的所有者。潜在的泄漏很容易找到。
缺点:如果可以从不同的线程创建对象,则需要锁定。额外的数据结构。

C)。通过要求对象的用户保存对对象的引用(例如,保存到 ivar)来避免自有习惯用法。

优点:不调用内存管理函数。对象有明确的所有者。
缺点:对象的用户必须保留一个引用,即使它不再需要该对象。额外的 ivars。

你会使用什么模式来处理这些情况?

4

2 回答 2

5

对于 a),更惯用的替代CFRetain(foo)/CFRelease(foo)[[NSGarbageCollector defaultCollector] disableCollectorForPointer:foo]/ [[NSGarbageCollector defaultCollector] enableCollectorForPointer:foo]

于 2008-10-28T18:06:32.707 回答
2

Apple 的推荐是 (c),但我喜欢 (b) 的声音。静态数据结构允许您向 API 用户隐藏 GC 详细信息,同时避免陷入 CFRetain/CFRelease 级别。正如您所说,它还使调试和单元测试更容易;如果一个对象在完成任务后仍然被静态数据结构引用,你就知道有一个错误。

于 2008-10-28T12:50:22.687 回答