【问题标题】:Is rethrowing an exception from catch block which has an nested exception okay?从具有嵌套异常的 catch 块中重新抛出异常可以吗?
【发布时间】:2014-10-27 15:13:54
【问题描述】:

想法是“尝试you(),如果失败则尝试_do(),如果失败则报告第一次尝试的异常,即you()”。

void that_thing() {
    try {
        you();
    } catch( ... ) {
        bool error=false;
        try {
            _do();
        } catch( ... ) {
            error = true;
        }
        if( error ) throw;
    }
}

用 Gcc 测试它工作正常,我想知道它是否适用于任何编译器。为了更清楚,我所期待的奇怪行为是 throw; 会重新抛出内部异常。

编辑:这个问题不是关于最内部的catch,而是关于在捕获最内部之后重新抛出外部异常。问题是这种重新抛出是否在法律上绝对没有被指出为类似的问题。

【问题讨论】:

  • 。我会说“当然它不会重新抛出内部异常”。考虑一个简单的try { foo(); } catch(...) { bar(); throw; }。我从未见过有人担心bar 在内部抛出并捕获异常时会发生什么。您能否扩展一下您认为可能会重新抛出内部异常的原因?更具体的问题可以获得更好的答案。
  • 如果没有参考标准或对此问题有任何特殊知识,我会冒险猜测它很好,编译器必须跟踪最外面的异常。否则,如果 _do() 在幕后使用 try/catch 本身并且它只是吞下了异常并被内联(甚至没有内联?),那么你的代码会发生不好的事情。
  • @hvd 我在想,如果你有一个天真的异常机制,它使用指向“当前异常”的全局指针,这个当前异常将在第二次捕获时被替换,从而在重新抛出指令。
  • @AndréPuel 啊,好的。是的,它不是那样工作的。我会检查是否能找到一个好的参考答案。

标签: c++ exception-handling


【解决方案1】:

该标准要求实现正确嵌套异常。引用标准:

15.1 抛出异常 [except.throw]

...

8 没有操作数的 throw-expression 会重新抛出当前处理的异常 (15.3)。

15.3 处理异常 [except.handle]

...

7 当 catch 子句的形式参数(如果有)的初始化完成时,处理程序被认为是活动的。 ... 当 catch 子句退出或 std::unexpected() 由于抛出而进入后退出时,处理程序不再被视为活动。

8 最近激活的处理程序仍处于活动状态的异常称为当前处理的异常

当您的代码到达throw; 时,内部异常处理程序不再处于活动状态:catch 子句已退出。外部异常处理程序仍然处于活动状态:它还没有退出,std::unexpected() 还没有被调用。因此,实现必须支持这种用法,并重新抛出外部异常。在内部处理程序退出后被清除的全局“当前异常”指针不符合 C++ 标准的要求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-14
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多