【问题标题】:run-time penalty of C++ try blocks [duplicate]C ++尝试块的运行时惩罚[重复]
【发布时间】:2012-02-06 23:32:02
【问题描述】:

可能重复:
Measuring exception handling overhead in C++
Performance when exceptions are not thrown (C++)

我听说在 C++ 中使用“try”块会在运行时减慢代码的运行速度,即使没有发生异常也是如此。我已经搜索过,但找不到任何解释或证据。有谁知道这是不是真的,如果是,为什么?

【问题讨论】:

标签: c++ exception-handling


【解决方案1】:

答案通常是“视情况而定”。

这取决于您的编译器如何实现异常处理。

如果您使用 MSVC 并针对 32 位 Windows,它使用基于堆栈的机制,每次输入 try 块时都需要一些设置代码,所以是的,这意味着您每次输入都会受到惩罚这样的块,即使没有抛出异常。

几乎所有其他平台(其他编译器,以及面向 64 位 Windows 的 MSVC)都使用基于表的方法,其中一些静态表在编译时生成,当抛出异常时,简单的表查找是执行,并且无需将设置代码注入到 try 块中。

【讨论】:

  • 但是插入 try/catch 会在任何(正确的)优化编译器中禁用优化(在一定程度上)。
  • 嗯?您指的是哪些优化,为什么?
  • 你的名字——循环优化(如果 try/catch 在循环中),公共子表达式消除等。编译器必须假设代码可以从 try 范围内的任何点跳转到catch 块,因此它不能很容易地跨尝试范围边界进行优化。
【解决方案2】:

有两种常见的实现异常的方法。

一种,有时称为“基于表”或“DWARF”,使用静态数据来指定如何从任何给定点展开堆栈;这没有运行时开销,除非抛出异常。

另一个,有时称为“基于堆栈”、“setjmp-longjmp”或“sjlj”,维护动态数据以指定如何展开当前调用堆栈。每当您进入或离开 try 块时,以及每当您使用非平凡的析构函数创建或销毁自动对象时,这都会产生一些运行时开销。

第一个在现代编译器中更常见(当然 GCC 默认已经做了很多年了);你必须检查你的编译器文档,看看它使用的是哪个,以及它是否可配置。

【讨论】:

  • DWARF 仅用于调试信息 AFAIK,绝不用于展开数据
  • @Hasturkun:展开堆栈所需的信息与调试所需的(部分)信息相同,因此至少 GCC 和 LLVM 两者都使用 DWARF,有时指的是基于表的处理为“DWARF 处理”。
猜你喜欢
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 2016-05-05
  • 2019-07-10
  • 2015-03-12
  • 2018-12-06
  • 2014-04-30
  • 2021-06-13
相关资源
最近更新 更多