16

一般来说,我倾向于将 try/catch 用于具有多个故障点的代码,这些故障点有一个共同的处理程序。

根据我的经验,这通常是在执行某些操作之前限定输入或上下文的代码,或者在执行某些操作之后限定输出。

我从文献和同事那里得到了建议,以尽量减少这些块中的代码,我接受这通常是好的建议。

我想更多地了解上述建议的基础:

  • 开销的性质是什么?
  • 是否有最近的开发指南来解决 try/catch 块的推荐使用(或避免)?
  • 更快的处理器和更现代的编译器在多大程度上缓解了 try/catch 的问题?

在此先感谢您的帮助,

阿杰

4

8 回答 8

18

在 c++ 中,成本取决于实现。一般来说,实现异常有两种方式:

第一个是“表”方法。编译器构建一组表来查找,在抛出异常的点,去哪里。当抛出异常时,它必须在调用堆栈中向上搜索每个表,直到找到可以捕获此异常的内容。由于这都是基于运行时的,因此进入或退出 try catch 不会产生任何惩罚(好),但抛出异常可能涉及许多查找,从而产生更慢的抛出。我个人更喜欢不为 try catch 块付费,因为异常应该是非常罕见的情况。如果它们必须存储表,这也会使可执行文件更大。

秒是“代码”方法。每次代码进入 try catch 块时,从概念上讲,块的位置被压入堆栈。这会在进入和退出 try-catch 块期间产生成本,但是,当抛出异常时,运行时机制可以快速弹出堆栈以查找去向。所以,抛出异常(很多?)更快,但现在进入一个块是有代价的。将 try catch 块放在紧密的低级别循环中可能会产生大量开销。

您必须检查您的特定编译器以查看他们使用的是哪一个。

于 2009-06-04T17:41:35.940 回答
7

我找到了一份关于 C++ 性能的技术报告(pdf 警告),其中包含关于异常的部分。你可能会觉得很有趣。我有同事认为 try/catch 块中的每条指令都有开销,但这份技术报告似乎并不支持这个想法。

于 2009-06-04T16:12:46.543 回答
5

对于你的第二个问题:一般指南在这里,Herb Sutter 在这里也给出了很好的建议。

于 2009-06-04T16:05:12.563 回答
2

取决于编译器。为什么不编写一个带有 try-catch 块的简单函数和一个没有它的类似函数,并比较生成的机器代码?

于 2009-06-04T17:24:27.727 回答
1

我发现 C++ FAQs 站点和相应的书对这个问题有启发性的讨论。

http://www.parashift.com/c++-faq-lite/exceptions.html

于 2009-06-04T17:35:49.537 回答
0

在 C++ 中,您不应该使用 try/catch 块来执行清理。相反,您可能希望使用模板来执行资源获取。

auto_ptr 是一个 [bad] 示例

同步锁,您将互斥锁存储为状态变量,并使用局部变量(模板或常规类)来执行 .acquire()/.release() 方法。

你做的越多,你就越不用担心在异常情况下手动释放对象。C++ 编译器会为你做这件事。

于 2009-06-04T19:42:48.243 回答
0

根据我的经验,try/catch 块的最大问题是我们经常尝试过于笼统地捕获异常。例如,如果我用一个捕获 (...) 的 try/catch 块包装我的 main 函数,我基本上是在试图不允许我的程序因抛出的异常而崩溃 b/c。

在我看来,这种方法的问题有两个。1) 在我进行测试和调试时,我没有看到任何错误,也没有机会修复它们。2)这真的是一种偷懒的方式。而不是考虑可能出现的问题并弄清楚边缘情况是什么,我只是尽量不失败。努力不失败与努力成功有很大不同。

于 2009-06-04T16:05:00.473 回答
0

在大多数语言中,通过普通方法进入和退出 try/catch 块是免费的,只有在抛出异常时,异常处理程序才会查找处理异常的位置。

于 2009-06-04T16:15:25.887 回答