【问题标题】:Why is terminate() called even if the unexpected_handler() throws a specified exception?即使意外处理程序()抛出指定的异常,为什么也会调用终止()?
【发布时间】:2011-11-05 22:00:24
【问题描述】:

考虑下面的代码:

#include <iostream>
#include <exception>

void third_party_function() throw () {
    throw -1; // oops
}

void recover() throw (std::exception) {
    std::cout << "We will throw std::exception() to avoid terminate() to be called.\n";
    throw std::exception();
}

int main(int argc, char** argv) {
    try {
        std::set_unexpected(recover);
        third_party_function();
    } catch (std::exception e) {
         std::cout << "Unexpected exception: " << e.what() << '\n';
    }
    return 0;
}

这是程序的输出:

我们将抛出 std::exception() 以避免调用 terminate()。 在抛出 'std::exception' 实例后调用终止
什么():标准::异常

我不明白为什么在任何情况下都会调用 terminate()(因此永远不会捕获 std::exception),尽管事实上我做了 Stroustrup 建议的类似示例以避免调用 terminate()在调用处理程序之后(参见 C++ 编程语言,第 3 版,第 14.6 章)

【问题讨论】:

  • 蛋糕是个谎言。不记录您正在使用的 CRT 没有多大意义。
  • CRT 代表什么?
  • C 运行时。记录您正在使用的编译器和操作系统。
  • Linux 2.6.31-22-generic-pae #73-Ubuntu SMP Fri Feb 11 18:39:01 UTC 2011 i686 GNU/Linux gcc 版本 4.4.1 使用内置规范。目标:i486-linux-gnu 线程模型:posix

标签: c++ exception


【解决方案1】:

third_party_function 承诺不会抛出任何异常。

因此,根据 C++98 §15.5.2/2,intstd::exception 类型的任何异常都会导致对 std::terminate 的调用。

如果它改为将自身限制为std::bad_exception,那么通过符合要求的实现,新异常将自动转换为std::bad_exception

在当前标准 C++11 中,已弃用使用关键字 throw 的这种异常规范。

然而,在 C++11 §15.5.2/3 中,C++11 的措辞与 C++98 相同。

另外,请注意,虽然 Visual C++ 确实允许该语法,但它从未尊重语义(可能除了 nothrow,现在记录为等同于使用无异常的语言扩展)。

因此,虽然它仍然是有效的标准 C++,但如果依赖异常规范来实现除 nothrow 之外的任何特定效果,它实际上是不可移植的。

【讨论】:

    【解决方案2】:

    这个想法是让意外处理程序在异常规范列表中抛出异常。由于third_party_function 异常规范没有抛出异常,所以它不起作用。但是,如果 third_party_function 在其异常规范中包含 std::exception,您的代码将可以工作。

    异常规范在 C++11 中已被弃用,也许你不应该使用它们。

    【讨论】:

    • 不,third_party_function() throw (std::exception) 不会改变这种行为。即使完全删除异常规范也不会改变它(在 Visual C++ 2010 上测试)。
    • @Branko Dimitrijevic:在 VC++2010 中进行测试是没用的,MSVC 从来没有也永远不会尊重异常规范。
    • recover()怎么没有被调用呢?
    • @Branko:这是用户错误的情况。 Visual C++ 不支持除 nothrow 之外的异常规范,因此您会得到 int 类型的异常直接传播到 main 中,在那里它不会被处理。您应该已经使用最初使用的编译器进行了测试。哦,我看你不是OP。但无论如何......
    • @K-ballo 但是int 异常未处理的事实应该触发recover(),对吧?
    猜你喜欢
    • 2015-10-04
    • 2021-06-19
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 2023-03-21
    • 2013-04-08
    相关资源
    最近更新 更多