objective-c: relying on dealloc



依赖确定性解除锁定(例如:用于清理)是合法的做法吗?

由于ARC,甚至手动引用计数,本质上是确定性的,我想知道其他人对依赖立即调用dealloc有什么看法(相对而言,考虑到自动释放池)。

在其他现代编程语言中,如C#,当您需要确定性清理时,会使用类似处置的模式。我想带有垃圾回收的Obj-C也会鼓励这种行为。

因此,一个例子是UIViewController,它取消了dealloc中未完成的操作,而不是试图围绕viewDidDisappear有时令人沮丧的语义进行编程。

另一个例子是一个流对象,它分别在init和dealloc中隐式打开和关闭,而不需要调用open或close。

由于苹果公司已经弃用GC,我想这些模式不会很快被打破,而且它们非常方便,尽管我找不到任何关于是否应该鼓励这样做的文档。

你是绝对正确的,你可以相信dealloc在最后一个引用发布后很快就会被调用(手动或通过ARC,这无关紧要)。与GC不同,在GC中,当系统有一些空闲时间时调用终结器,或者在某些情况下从未调用过终结器,dealloc的调用非常可靠。苹果允许甚至鼓励使用这种模式,建议我们在dealloc中执行所有的资源清理任务。

但是,这并不意味着您应该完全依赖dealloc。例如,看看NSStream类:它为您提供了一个显式的close方法,允许您随意强制关闭流,而无需等待dealloc的调用。在资源非常昂贵(文件句柄、信号量等)的情况下,这是一个非常好的模式:释放这些资源的主要机制应该是一个单独的close方法。dealloc方法也应该释放资源,但它也应该发出警告,通知您错过了对close的调用。

无论您的内存管理系统如何,将昂贵的资源(如文件和套接字、图像、视图、大内存分配等)与对象生存期捆绑在一起都是有风险的。即使您手动保留&释放时,您可能会无意中将对象保留在某个位置,然后忘记它(或者不必要地延迟它的释放)。ARC使这些事情更有可能发生,因为保留来自哪里以及相应的发布何时生效都不太明显。当然,GC让这一切变得完全不确定。

一般来说,对于昂贵和/或有限的资源,您应该尝试遵循独资模式。是的,您仍然可以正常保留/释放,以防止过早解除分配,但主要所有者应该明确定义,并负责在对象完成时清除对象,例如调用invalide、close或其他适当的方法。这在很多常见情况下都是非常合理的——例如,您通常知道什么时候处理完文件或套接字,所以即使它们碰巧被封装在某个包装器类中,也应该显式关闭它们。

在某些情况下,这也有助于找到那些原本会隐藏或难以追踪的错误。例如,如果文件包装器类在文件关闭后调用读或写时引发异常,那么您很快就会发现这些情况。然而,如果你在认为你已经处理完了时没有关闭文件,那么读写操作将照常进行,你可能不会注意到你的文件中有意外的数据。

您也可以使用相同的原则来打破保留周期。

最新更新