【问题标题】:How to turn off exception handling?如何关闭异常处理?
【发布时间】:2016-02-12 11:23:00
【问题描述】:

在《更有效的 C++》(第 15 期)一书中,我读到如果启用异常,即使不使用它们,代码也会显着变慢。在我看来,异常的用处有限,我尽量避免它们,但这是另一个话题。

我不完全理解他的说法:

  1. 启用/禁用异常是什么意思?它是具有零个或多于零个 try/catch 块之间的区别吗?它是编译器标志吗?如果我使用可能发生异常的 DLL,会发生什么情况?
  2. 假设没有抛出异常:
    • 是整个代码变慢了还是只是程序进入/退出 try/catch 块的部分变慢了?根据作者的说法,两者都是正确的。
  3. 如何编译不出现异常?即使我有 try/catch 块,我也可以这样做吗?如果我使用的 DLL 可能引发异常,我可以这样做吗?

【问题讨论】:

  • 这本书很老了,从那时起编译器就变得更聪明了。今天一个体面的可以零开销地做到这一点,使用基于表的查找指令地址来查找需要在堆栈展开时运行的代码。但是,如果您无论如何都想为此烦恼,请查看编译器选项,大多数都可以选择禁用该功能。
  • " 在我看来,异常的用处有限,我尽量避免它们,但这是另一个话题。"我的猜测是你的代码没有调用任何错误的系统调用。你在给 CPU 加热器编程吗?
  • @user4590120:异常不是处理失败的唯一方法。我使用返回码来检查成功或失败。

标签: c++ performance exception-handling


【解决方案1】:

启用/禁用异常是什么意思?

向编译器传递一个标志,该标志禁用与异常相关的标准一致性,并使其不生成任何异常支持。

如果我使用可能发生异常的 DLL 会发生什么?

如果某些库在内部处理异常,则没有。如果它让它逃逸给调用者(由于 ABI 问题,我从未见过任何这样做的库,但无论如何),您的程序将崩溃(在最好的情况下),因为它无法处理它。如果您的代码包含 DLL 的包装器并将错误代码转换为异常(常见),那么它与您在代码中使用异常相同。

是整个代码变慢了还是只是程序进入/退出 try/catch 块的部分变慢了?根据作者的说法,两者都是正确的。

请注意,您引用的那本书很旧。编译器正在发展。现代编译器使用零成本异常,如果不抛出异常,则不会产生性能成本。异常处理确实使可执行文件更大,因为它应该生成处理异常所需的所有数据和代码,但它不应使其在非异常路径上变慢。

如何编译没有异常?即使我有 try/catch 块,我也可以这样做吗?

您以特定于编译器的方式执行此操作。请查阅您的编译器文档。通常这样做会使编译器拒绝包含任何异常相关设施的代码,例如指出 try 为无法识别的标识符。

【讨论】:

  • “异常处理确实使可执行文件更大” - 比什么大?具有错误返回值的等效程序也需要代码和数据来处理这些。异常的一大优势是错误处理代码和数据最初可以留在磁盘上,因此您的程序启动速度更快。
  • “它不应该让它在非异常路径上变慢” - 事实上,现代异常处理使非错误路径更快。这是因为编译器可以识别和优化该路径。对于错误返回值,编译器不知道是优化==0还是!=0返回值,因为不同的函数使用不同的返回值约定。
  • @MSalters 比在没有异常支持的情况下编译的完全相同的代码(这意味着原始代码必须完全没有异常处理)。这摆脱了标准库的异常处理(例如,new 通常会变成 nothrow new,稍后将bad_alloc 异常替换为空指针访问崩溃)
  • 嗯,删除功能(错误处理或其他)通常会使程序更小。这不是一个有意义的观察。
  • 我的 dll 抛出了很长时间以来的错误,调用程序在没有崩溃的情况下捕获了它们,但打印出了通过 what() 返回的消息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 2017-11-19
  • 2021-07-29
  • 2011-02-07
相关资源
最近更新 更多