简体   繁体   English

为什么bad_exception不会自动抛出?

[英]Why bad_exception is not thrown automatically?

Why doesn't this piece of code run without error? 为什么这段代码没有错误运行? Isn't bad_exception supposed to be called automatically when an unexpected exception is encountered? 遇到意外异常时,难道不应该自动调用bad_exception吗? Or is it necessary to set a handler for it? 还是有必要为其设置处理程序?

#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 ";
    }
}

In C++03 theory: If you throw an exception that is not in the exception specification, unexpected() gets called. 在C ++ 03理论中:如果引发的异常不在异常规范中,则将调用unexpected() If you have not set the unexpected handler via set_unexpected() this means terminate() gets called which is the case you observed. 如果您尚未通过set_unexpected()设置意外的处理程序, set_unexpected()这意味着您将观察到terminate()被调用的情况。 If you have set an unexpected handler that does not call terminate but throws an exception, and if that exception is not listed in your exception specification, it gets translated into bad_exception. 如果设置一个意想不到的处理程序不调用终止,但抛出一个异常,如果该异常不能在你的异常规范中列出,它被翻译成bad_exception。 So in order to get the expected result, call set_unexpected() first with an appropriate handler. 因此,为了获得预期的结果,请首先使用适当的处理程序调用set_unexpected()

In C++03 practice: Some compilers do not support exception specifications at all (other than throw() ), others just don't evaluate/check them for correctness. 在C ++ 03的实践中:有些编译器根本不支持异常规范( throw()除外),其他编译器只是不评估/检查其正确性。 As Herb Sutter points out , exception specifications create a clumsy "shadow type system" that is not easy to handle right (if it is possible at all). 正如Herb Sutter指出的那样 ,异常规范创建了一个笨拙的“影子类型系统”,该系统很难正确处理(如果可能的话)。 Therefore.. 因此..

... in C++11: Exception specifications are deprecated . ...在C ++ 11中: 不赞成使用 Exception规范。 You should rather not use them. 您宁可不要使用它们。 However, there is a nothrow operator that has a slightly different functionality than throw() 但是,有一个nothrow运算符的功能与throw()略有不同


PS: so why have std::bad_exception in C++03? PS:那么为什么C ++ 03中有std :: bad_exception? You hav three different regions of code: 您拥有三个不同的代码区域:

  • The function you are writing an exception specification for. 您正在为其编写异常规范的函数。
  • The "foreign" code you are calling from that function that might or might not throw an exception that does not match you specification. 您从该函数调用的“外部”代码可能会或可能不会引发与您的规范不匹配的异常。
  • The (maybe also unknown) unexpected handler that can be anything and should either terminate/exit/abort the program or throw anything. (可能也是未知的)意外的处理程序可以是任何东西,应该终止/退出/中止程序或抛出任何东西。

So if the "foreign" code throws an exception that violates your exception specification, you have three possible outcomes of that: 因此,如果“外来”代码引发了违反您的异常规范的异常,则可能会产生以下三种结果:

  1. The handler terminates the program. 处理程序终止程序。 There is not much you can do about that unless you set your own handler in the function. 除非您在函数中设置自己的处理程序,否则您将无能为力。
  2. The handler throws an exception that matches your exception specification. 处理程序将引发与您的异常规范匹配的异常。 And all is well. 一切都很好。
  3. The handler throws something else. 处理程序会抛出其他内容。 What do you want the runtime to do now? 您希望运行时现在做什么? That's where bad_exception comes in: If it is in your specification, the "something else" gets translated into a bad_exception, and the program continues. 这就是bad_exception出现的地方:如果在您的规范中,则“其他”将转换为bad_exception,然后程序继续。 If it's not, terminate gets called. 如果不是,则终止被调用。

Setting your own handler inside the function disables any handler that was previously set by anyone else who just wants to use your function. 在函数内设置自己的处理程序将禁用任何其他仅想使用您的函数的人先前设置的处理程序。 He will not expect you to disable his handler. 他不会期望您禁用他的处理程序。 Besides, the handler is meant as a global what-happens-if policy and thus is nothing you should care about in a single function implementation. 此外,该处理程序是一种全局的“假设-如果”策略,因此您在单个函数实现中就不必担心。

This should call std::unexpected which by default call std::terminate() as the thrown exception isn't part of the exception specification. 这应该调用std::unexpected ,默认情况下调用std::terminate()因为抛出的异常不是异常规范的一部分。

(It does here with g++ on Linux, Sun Oracle CC on Solaris, IBM xlC on AIX BTW) (此处适用于Linux上的g ++,Solaris上的 Sun Oracle CC,AIX BTW上的IBM xlC)

If you install an unexpected handler, it works as you expect here: 如果您安装了意外的处理程序,它将按您期望的那样工作:

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 ";
    }
}

As per [except.unexpected], when a function throws an exception not listed in its dynamic exception specification, std::unexpected() is called. 按照[except.unexpected],当一个函数抛出其动态异常规范中未列出的异常时,将调用std::unexpected() According to [unexpected.handler], the default implementation of std::unexpected() simply calls std::terminate() . 根据[unexpected.handler], std::unexpected()的默认实现只是调用std::terminate()

However, the program can install its own handler, which can (re-)throw an exception. 但是,程序可以安装自己的处理程序,该处理程序可以(重新)引发异常。 If the exception thus thrown is not allowed by the dynamic exception specification, it can be replaced by std::bad_exception when that is allowed. 如果由此引发的异常不会被动态异常规范允许,它可以被替换std::bad_exception 允许的时候。

Your catch-block would only catch exceptions of the type bad_exception , or a subtype thereof. 您的catch块将仅捕获bad_exception类型或其子类型的异常。 C does not meet this criterion. C不符合此条件。

Actually, this question is very similar to yours. 实际上, 这个问题与您的问题非常相似。 The accepted answer explains that if your function throws an exception that does not match the specification (if there is any), then std::unexpected is called, which by default calls std::terminate . 可接受的答案说明,如果您的函数抛出与规范不匹配的异常(如果存在),则将调用std::unexpected ,默认情况下将调用std::terminate

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

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