异常处理中的混乱

Pra*_*rav 3 c++

考虑以下程序

#include <iostream>
#include<cstdlib>
using namespace std;

class E {
   public:
      const char* error;
      E(const char* arg) : error(arg) { }
};

void my_terminate() {
  cout << "Call to my_terminate" << endl;
}

struct A {
  A() { cout << "In constructor of A" << endl; }
  ~A(){
    cout << "In destructor of A" << endl;
    throw E("Exception thrown in ~A()");
  }
};

struct B {
  B() { cout << "In constructor of B" << endl; }
  ~B() { cout << "In destructor of B" << endl; }
};

int main() {

  set_terminate(my_terminate);

  try {
    cout << "In try block" << endl;
    A a;
    B b;
    throw E("Exception thrown in try block of main()"); // Line 36
  }
  catch (E& e) {
    cout << "Exception: " << e.error << endl;
  }
  catch (...) {
    cout << "Some exception caught in main()" << endl;
  }

  cout << "Resume execution of main()" << endl;

}
Run Code Online (Sandbox Code Playgroud)

输出:

In try block
In constructor of A
In constructor of B
In destructor of B
In destructor of A
Call to my_terminate

Disallowed system call: SYS_kill
Run Code Online (Sandbox Code Playgroud)

在第36行中,从main中的try块抛出异常.现在为什么这个异常没有被处理程序捕获?

相反,'堆栈展开'过程继续.A的析构函数也抛出一个异常,它再次没有被任何处理程序捕获,而是调用my_terminate了,为什么?

为什么在这两种情况下不调用处理程序?

Reu*_*nen 17

C++规则是,您必须永远不要从另一个异常的"堆栈展开"过程中调用的析构函数中抛出异常.

你在A析构函数中抛出异常,这是你不应该做的事情.

  • 从我链接的FAQ:"在堆栈展开期间,所有这些堆栈帧中的所有本地对象都被破坏.如果其中一个析构函数抛出一个异常(比如它抛出一个Bar对象),那么C++运行时系统就处于 - 胜利局面:它应该忽略Bar并最终进入} catch(Foo e){它最初的位置?它应该忽略Foo并寻找} catch(Bar e){handler?没有好的答案 - 要么选择丢失信息.所以C++语言保证它会在此时调用terminate(),并终止()杀死进程.让你死了." (3认同)
  • 在try {}范围内声明的对象需要首先被破坏,因为它们在外部不可见,甚至在catch块中也看不到.而且因为A的析构函数表现不佳,所以从未到达过处理程序. (2认同)