0

为什么这段代码不能正常运行?遇到意外异常时不bad_exception应该自动调用吗?还是有必要为它设置一个处理程序?

#include <iostream>
#include <exception>
using namespace std;
class C{};
void test() throw(bad_exception)
{
    throw C();
}
int main()
{
    try
    {
         test();
    } catch(bad_exception& e)
    {
        cout << "Caught ";
    }
}
4

4 回答 4

3

在 C++03 理论中: 如果你抛出一个不在异常规范中的异常,unexpected()就会被调用。如果您没有通过set_unexpected()这种方式设置意外处理程序terminate(),则会调用您观察到的情况。如果您设置一个不调用终止但抛出异常的意外处理程序,并且如果该异常未在您的异常规范中列出,它将被转换为 bad_exception。因此,为了获得预期的结果,set_unexpected()首先使用适当的处理程序进行调用。

在 C++03 实践中: 一些编译器根本不支持异常规范(除了throw()),其他编译器只是不评估/检查它们的正确性。正如Herb Sutter 所指出的,异常规范创建了一个笨拙的“影子类型系统”,不容易正确处理(如果可能的话)。所以..

... 在 C++11 中:不推荐使用 异常规范。你不应该使用它们。但是,有一个nothrow运算符的功能与throw()


PS:那么为什么在 C++03 中有 std::bad_exception 呢? 您有三个不同的代码区域:

  • 您正在为其编写异常规范的函数。
  • 您从该函数调用的“外部”代码可能会或可能不会引发与您的规范不匹配的异常。
  • (可能也是未知的)意外处理程序可以是任何东西,应该终止/退出/中止程序或抛出任何东西。

因此,如果“外部”代码抛出了违反您的异常规范的异常,您可能会出现以下三种结果:

  1. 处理程序终止程序。除非您在函数中设置自己的处理程序,否则您无能为力。
  2. 处理程序抛出与您的异常规范匹配的异常。一切都很好。
  3. 处理程序抛出其他东西。您希望运行时现在做什么?这就是 bad_exception 出现的地方:如果它在您的规范中,则“其他内容”会被转换为 bad_exception,然后程序继续。如果不是,则调用 terminate。

在函数中设置您自己的处理程序会禁用之前由只想使用您的函数的任何其他人设置的任何处理程序。他不会期望你禁用他的处理程序。此外,处理程序是一个全局的what-happens-if 策略,因此在单个函数实现中你不应该关心任何事情。

于 2012-11-27T09:31:36.830 回答
2

这应该调用std::unexpected默认调用std::terminate(),因为抛出的异常不是异常规范的一部分。

(在 Linux 上使用 g++,在 Solaris 上使用Sun Oracle CC,在 AIX BTW 上使用 IBM xlC)

如果你安装了一个意外的处理程序,它会像你期望的那样工作:

include <iostream>
#include <exception>
using namespace std;
class C{};

void myunexpected()
{
    throw std::bad_exception();
}

void test() throw(std::bad_exception)
{
    throw C();
}
int main()
{
    try
    {
        set_unexpected(myunexpected);
        test();
    } catch(std::bad_exception& e)
    {
        std::cout << "Caught ";
    }
}
于 2012-11-27T09:15:33.210 回答
1

根据 [except.unexpected],当函数抛出未在其动态异常规范中列出的异常时,std::unexpected()将被调用。根据[unexpected.handler],std::unexpected()简单调用的默认实现std::terminate()

但是,程序可以安装自己的处理程序,它可以(重新)抛出异常。如果动态异常规范不允许由此引发的异常,则可以将其替换为何std::bad_exception允许。

于 2012-11-27T09:24:17.893 回答
0

您的 catch-block 只会捕获 typebad_exception或其子类型的异常。C不符合这个标准。

其实这个问题和你的很相似。接受的答案解释说,如果您的函数抛出与规范不匹配的异常(如果有),则std::unexpected调用,默认情况下调用std::terminate.

于 2012-11-27T09:14:53.917 回答