【问题标题】:Throwing an exception while throwing an exception抛出异常时抛出异常
【发布时间】:2013-05-24 03:12:19
【问题描述】:

这段代码:

#include <iostream>
#include <stdexcept>

using namespace std;

int throw_it() {
  throw range_error( "foo" );
}

int main() {
  try {
    throw throw_it();
  }
  catch ( exception const &e ) {
    cerr << e.what() << endl;
    return 0;
  }
}

在运行时打印foo,但是否保证会这样做?更具体地说,在抛出异常的过程中抛出异常会导致定义的行为吗?这种行为是否会引发最近抛出的异常(就像上面的测试代码一样)?

仅供参考:

$ g++ --version
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)

【问题讨论】:

  • 我现在太累了,但是 this here 似乎是一篇关于该主题的有趣文章。
  • @StefanFalk Windows SEH 和 C++ 异常是两个不同的东西。
  • 您不是“正在抛出异常”。你正在调用一个函数并计划使用它的返回值来抛出,但是当函数实际上没有返回时,你的计划就毁了。

标签: c++ exception-handling


【解决方案1】:

一次只能评估一个异常。从 15.1/7 开始

如果异常处理机制在完成对要抛出的表达式的求值之后但在捕获异常之前调用通过异常退出的函数,则调用 std::terminate。

在您的示例中,std::terminate() 未被调用,因为实际上只抛出了一个异常。当达到throw throw_it(); 时,首先评估throw_it(),这导致在实际引发异常之前调用该函数。由于该函数抛出异常并且永远不会返回原始的throw,因此永远不会到达。如果throw_it() 没有抛出异常并返回一个整数值,则调用throw 表达式将被执行。因此,对于您的示例,foo 保证会被打印出来。

但是从活动处理程序中抛出一个新异常呢?当捕获到异常时,它已被完全评估。当您抛出一个新异常(而不是用“throw;”重新抛出)时,原始异常被销毁并开始评估新异常。

从 15.1/4 开始

异常对象在最后一个剩余的异常活动处理程序以除重新抛出之外的任何方式退出后被销毁,或者......

这满足了一次只能评估一个异常的规则。

【讨论】:

    【解决方案2】:

    更具体地说,在处理过程中是否抛出异常 抛出异常会导致定义的行为?

    只要不是在构造异常对象之后捕获它之前就可以了,因为那时会调用std::terminate。在您的示例中,根本没有创建异常对象,因此没有什么要抛出的,而是抛出了range_error("foo")。这是要捕获的异常。

    你可以这样检查:

    int throw_it() {
        throw range_error( "foo" );
        return 19;
    }
    
    int main() {
        try {
            try { // nested try is perfectly legal
                throw throw_it();
            } catch (...) {
                cerr << "not good!";
            }
        } catch (exception const &e) {
            cerr << e.what() << endl;
            return 0;
        }
    }
    

    输出:

    not good!
    
    RUN SUCCESSFUL (total time: 59ms)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      • 2013-07-24
      • 2011-02-25
      • 2012-01-24
      • 2019-12-27
      相关资源
      最近更新 更多