在Objective-C中使用异常的代价是什么?

9

我的意思是在当前的clang或gcc版本实现中。

C++和Java开发人员总是告诉我,除非抛出异常,否则异常不会影响性能。Objective-C也是如此吗?


我非常确定C++的开发人员通常会告诉你,除非抛出异常,否则异常的代价是微不足道的。 - Georg Fritzsche
2个回答

9
<简短回答> 仅在64位OS X和iOS中。
它们并不完全免费。更准确地说,该模型被优化以在正常执行期间最小化成本(将后果转移至其他地方)。 <详细回答> 在32位的OS X和iOS上,即使未抛出异常,异常也会有运行时成本。这些架构不使用零成本异常。
在64位的OS X中,ObjC转而借用了C ++的“零成本异常”。除非抛出,否则零成本异常的执行开销非常低。零成本异常有效地将执行成本移动到二进制大小。这是它们最初未在iOS中使用的主要原因之一。启用C++异常和RTTI可以将二进制大小增加50%以上-当然,我预计在纯ObjC中,这些数字会远低于此,因为解缠时执行的内容较少。
在arm64中,异常模型从Set Jump Long Jump更改为Itanium派生的零成本异常(根据汇编判断)。
然而,惯用的ObjC程序并不是为了从异常中恢复而编写或准备的,因此您应该将它们保留用于您不打算从中恢复的情况(如果您决定使用它们)。更多细节请参见Clang manual on ARC和引用页面的其他部分。

3
此外,您还应该指出异常对ARC的问题:http://clang.llvm.org/docs/AutomaticReferenceCounting.html -“默认情况下通过异常使代码安全将对通常实际上并不关心异常安全性的代码产生严重的运行时和代码大小惩罚。因此,ARC生成的代码在异常情况下默认会泄漏,如果进程无论如何都将立即终止,这是没有问题的。” - Brad Larson
@BradLarson 很好的参考资料--谢谢+1,并添加了。值得注意的是,只有在执行时ARC才真正特定于__weak对象的生命周期结束,除非编译器禁用异常。链接的描述确实有助于限定为什么ObjC程序无法可靠地(以明确定义的方式)从异常中恢复的示例。 - justin
这对我来说没问题。希望他们保持这种方式 :-) 作为一名Eiffel程序员,我讨厌异常并且极其有限地使用它们。 - Lothar
@Justin,感谢您的回答!请问64位iOS是否支持“零成本异常”? - FreeNickname
1
@FreeNickname 更新了答案。感谢指出需要更新的问题。 - justin

6
根据Mac OS X v10.5中Objective-C运行时的一些2007年发布说明,他们已经重新编写了Objective-C异常的64位实现,以提供“零成本”的try块和与C ++的互操作性。
显然,这些“零成本”try块在进入try时不会产生时间惩罚,而其32位对应项必须调用setjmp()和其他函数。显然,抛出它们是“更加昂贵”的。
这是我在苹果发布说明中唯一能找到的信息,因此我必须假设这仍然适用于今天的运行时,因此,32位异常=昂贵,64位异常=“零成本”。

为了完整性,64位零成本C++兼容异常 - Jeffery Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接