繁体   English   中英

C ++异常抛出/捕获优化

[英]C++ Exception Throw/Catch Optimizations

在我看来,如果你有一些像这样的C ++代码:

int f()
{
  try {
    if( do_it() != success ) {
      throw do_it_failure();
    }
  } catch( const std::exception &e ) {
    show_error( e.what() );
  }
}

C ++编译器应该能够优化throw并捕获几乎简单的goto。

但是,从我查看反汇编和单步执行代码的经验来看,编译器总是跳过非常混乱的异常处理库。

他们为什么这样做? 是否存在一些阻止优化的语言要求? 如果它是:

int f()
{
  try { throw std::runtime_error("Boo!"); }
  catch ( const std::exception &e ) { std::cout << e.what() << std::endl; }
}

为什么编译器不只是重写为

int f()
{
  std::cout << "Boo!" << std::endl;
}

因为在抛出do_it_failure();之前, do_it()可能抛出不同的异常do_it_failure();

至于你的第二个例子,编译器可以做到这一点,但它必须被视为一个特例,那么为什么还要为这种病态案例而烦恼呢?

他们为什么这样做?

因为C ++例外适用于, 特殊情况下的特殊情况和性能并不重要。

考虑到这一点,设计了C ++的异常,确保编译器供应商可以在没有异常抛出的常见情况下提供接近最优的性能,但是在抛出异常的奇怪情况下,代价可能性能更差。

从一开始就鼓励用户仅在特殊情况下使用异常,并且鼓励实现者优化无异常情况(析构函数地址必须存储在某处以便在异常发生时调用析构函数),代价是异常案件。
虽然实施者当然可以花费资源来优化奇怪的例外情况,但大多数用户都不喜欢这样,因为总是有更重要的东西需要改进。

我认为,如果没有错误,接受的答案是非常缺乏信息的,所以即使经过这么多年,我觉得有必要提供正确的答案。

推测为什么编译器实现者选择不对任何特定功能付出努力只是......好猜测。 仅在特殊情况下抛出异常的事实通常不被认为是不优化此类代码性能的理由。 相反,尽管抛出代码并没有非抛出代码为代价进行优化,但抛出和处理异常的例外情况仍然非常谨慎地进行了优化。

此外,这段代码可能感觉如此做作,不值得考虑,但事实并非如此:它可能来自内联和优化更复杂的代码,并且优化它可能导致更简单的代码,允许其他优化传递触发,或包含进一步内联的函数。 无论原始代码看起来多么做作,这些优化传递都是正确的,有效的实现,总是值得至少考虑。 否则,即使是死代码消除的基本过程也会被避免,因为“死代码不应该首先写入”。 这显然不是这样的。

因此,我只是不同意接受的答案。 应该异常抛出异常的事实并不是未对此代码进行优化的原因。

原因纯粹是技术性的,并在clang开发邮件列表的电子邮件中进行了解释: http//lists.llvm.org/pipermail/cfe-dev/2015-March/042035.html

总而言之,该语言允许在catch块内调用的代码在“没有看到”异常对象的任何点重新抛出异常:

void g() { throw; }

因此,考虑OP代码:

int f()
{
  try { throw std::runtime_error("Boo!"); }
  catch ( const std::exception &e ) { std::cout << e.what() << std::endl; }
}

对于编译器而言, e.what()operator<<的两次调用可能会重新抛出异常,因此优化掉异常处理代码会破坏程序的语义。

确保不是这种情况需要“整个程序知识”,如上面的电子邮件中所述。 即使是简单的情况下, 可以优化,如:

int func() {
  try {
    throw 42;
  }catch(int x) {
    return x;
  }
}

上面的代码可以转换为return 42 没有技术原因阻碍它。

尽管如此,大多数常见的编译器都没有这样做( godbolt )。 这一次,我们可以从实际来源,上面链接的电子邮件,Clang开发人员(我们不能为其他编译器说什么)不认为这个优化是值得的, 可能是因为它只适用于不执行的catch块函数调用。

无论如何,该消息没有说明他们是否会接受这样做的补丁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM