在资源不是自动管理的情况下抛出异常是不安全的。Cocoa 框架(和相邻框架)就是这种情况,因为它们使用手动引用计数。
如果抛出异常,release
通过展开堆栈跳过的任何调用都将导致泄漏。仅当您确定不会恢复时,这应该限制您投掷,因为当进程退出时所有资源都返回给操作系统。
不幸的是,NSRunLoop
s 倾向于捕获传播给它们的所有异常,因此如果您在事件期间抛出,您将继续到下一个事件。这显然是非常糟糕的。因此,最好不要扔。
如果您使用垃圾收集的 Objective-C,这个问题就会减少,因为任何由 Objective-C 对象表示的资源都将被正确释放。但是,未包装在 Objective-C 对象中的 C 资源(例如文件描述符或malloc
分配的内存)仍然会泄漏。
所以,总而言之,不要扔。
正如您所提到的,Cocoa API 对此有几种解决方法。回归nil
和NSError**
模式是其中的两个。
对 ARC 的说明
ARC 用户可以选择启用或禁用完全异常安全。启用异常安全后,ARC 将生成代码以在其作用域被终止时释放强引用,从而可以安全地在代码中使用异常。ARC 不会修补外部库以在其中启用异常支持,因此即使在程序中启用了异常支持,您也应该小心抛出的位置(尤其是捕获的位置)。
可以使用 启用-fobjc-arc-exceptions
或禁用ARC 异常支持-fno-objc-arc-exceptions
。默认情况下,它在 Objective-C 中是禁用的,但在 Objective-C++ 中是启用的。
默认情况下,Objective-C 中的完全异常安全是禁用的,因为 Clang 作者假设 Objective-C 程序无论如何都不会从异常中恢复,并且因为与清理相关的代码大小成本和性能损失很小。另一方面,在 Objective-C++ 中,C++ 已经引入了大量的清理代码,人们更可能需要异常安全。
这全部来自LLVM 网站上的 ARC 规范。