不抛出异常的情况下的性能表现(C++)

12

我已经阅读了很多有关C++异常的内容,特别是异常性能是一个难题。我甚至尝试着去查看g++如何在汇编中表示异常。

作为一名C程序员,我更喜欢低级语言。不久前,我决定使用C++而非C,因为用很小的代价可以让我的生活更轻松(类优于结构体,模板等)。

回到我的问题,据我所见,异常只有在发生时才会产生额外开销,因为它需要一长串跳转和比较指令来找到合适的异常处理程序。在正常程序执行(没有错误的情况下),异常的开销与正常的返回代码检查相当。我对吗?


感谢标题中的“again”后缀。 - user395760
1
我认为答案是与编译器相关的。 - Merlyn Morgan-Graham
3
如果你想知道性能影响,就要 进行测试 - Greg Hewgill
3
如果我没记错的话,现代平台上的现代实现在没有异常路径时有零开销。您可能想要查看“C++性能报告”,您可以从http://www.open-std.org/jtc1/sc22/wg21/下载。 - sellibitze
在许多情况下,类似C语言手动错误检查变得非常复杂,以至于程序员产生的开销比使用异常的平均编译器开销还要大。 - mbq
@Sellibitze:谢谢,我有时间的时候会阅读这个 :) - Matthieu M.
2个回答

14
请查看我对类似问题的详细回答这里
异常处理开销是与平台相关的,它取决于你所运行的操作系统、编译器和CPU架构。
对于Visual Studio、Windows和x86架构,在没有抛出异常时也会产生一定的开销。编译器会生成额外的代码来跟踪当前“作用域”,以便确定要调用哪些析构函数,并在哪里开始搜索异常过滤器和处理程序。作用域的变化由 try 块和具有析构函数的对象的创建触发。
对于Visual Studio、Windows和x86-64架构,当没有抛出异常时,该成本基本为零。 x86-64 ABI比x86更严格地规定了异常处理协议,而操作系统则进行了大量工作,因此程序本身不需要跟踪太多信息来处理异常。
当异常发生时,开销是显著的,这就是为什么它们只应该在真正的异常情况下发生的原因。在x86-64架构上处理异常比在x86上更加昂贵,因为该架构被优化为异常不会发生的常见情况。

我知道已经过去了3年,但是在Linux x86-64上开销是否也很小呢? - contrapsych
1
@JAKE6459 我不能确定地回答,但是 x86-64 相对于 x86 的一个好处是异常的支持方式,我相信 Linux 利用了这一点。如果你真的需要知道的话,建议使用性能分析工具对你的代码进行分析,如果你在 Linux 上使用 C/C++,可以尝试使用 gprof - Chris Schmich
你能诚实地说,关闭异常后编译的代码没有明显的速度优势吗? - John McFarlane

5
这是异常处理成本的详细评估,即使没有实际抛出异常,在使用异常处理的每个函数(具有try / catch块或具有析构函数的自动对象)中,编译器都会生成一些额外的前缀/后缀代码来处理异常注册记录。此外,每次自动对象构造和析构后,还会添加一些汇编指令(调整异常注册记录)。此外,有些优化可能会被禁用,特别是在所谓的“异步”异常处理模型中工作时这种情况更为常见。请参考:http://www.nwcpp.org/old/Meetings/2006/10.html

2
提醒一下,所提供的链接目前已经失效了。 :-/ - Charles L Wilcox
我认为当前URL是https://nwcpp.org/october-2006.html。 - JuanMoreno

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