为什么代码会崩溃?

And*_*ndy 0 c++ exception

在互联网上寻找C++脑筋急转弯,我发现了这个例子:

#include <iostream>

using namespace std;

class A {
public:
    A()
    {
        cout << "A::A()" << endl;
    }

    ~A()
    {
        cout << "A::~A()" << endl;
        throw "A::exception";
    }
};

class B {
public:
    B()
    {
        cout << "B::B()" << endl;
        throw "B::exception"; // <- crashes here
    }

    ~B()
    {
        cout << "B::~B()";
    }
};

int main(int, char**) {
    try
    {
        cout << "Entering try...catch block" << endl;

        A   objectA;
        B   objectB;

        cout << "Exiting try...catch block" << endl;
    }
    catch (const char* ex)
    {
        cout << ex << endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这就是我认为该程序会做的事情:

  1. 调用objectA的构造函数时,A :: A()将输出到屏幕.对象A构造成功.
  2. 调用objectB的构造函数时,B :: B()将输出到屏幕.
  3. 然后B的构造函数抛出异常.对象B未构建成功.
  4. 不会调用objectB的析构函数,因为构造函数从未成功完成.
  5. 当退出try块时,对象超出范围时将调用objectA的析构函数.

但是,当我运行该程序时,它实际上在标有< - 的行上崩溃了.有人可以解释那时到底发生了什么吗?

Tad*_*pec 11

如果你真的在编码,那么不仅仅是脑筋急转弯 从不会从析构函数中抛出异常.如果在堆栈展开期间抛出异常,terminate()则调用.在你的情况下,在处理B的构造函数中抛出的异常时抛出了A的析构函数.

编辑:更准确(如评论中所建议) - 永远不要让异常逃避析构函数.析构函数中捕获的异常没有问题.但是如果在堆栈展开程序期间必须处理两个异常 - 导致堆栈展开的异常和在展开期间转义析构函数的异常,std::terminate()那就去了.


sha*_*oth 6

B::B()抛出一个异常堆栈展开开始.A::~A()被调用并抛出另一个未被捕获的异常A::~A().

如果正在进行堆栈展开时另一个异常会离开析构函数,则会调用terminate()并且看起来像程序崩溃.