3

I'm trying to understand why throwing an exception from a destructor results in a program crash. As I found many examples of two object which throw multiple exception and compiler can't handle multiple exception but in my case I only have a single exception thrown from the destructor. Why is my program still crashing?

class MyClass {
private:
    string name;
public:
    MyClass (string s) :name(s) {
        cout << "constructor " << name << endl;
    }
    ~MyClass() {
        cout << "Destroying " << name << endl;
        throw "invalid";
    }
};
int main( ) 
{ 
    try {
        MyClass mainObj("M");
    }
    catch (const char *e) {
        cout << "exception: " << e << endl;
        cout << "Mission impossible!\n";
    }   
    catch (...) {
        cout << "exception: " <<  endl;
    }
    return 0; 
}
BDL
  • 21,052
  • 22
  • 49
  • 55
Sagar
  • 171
  • 1
  • 6
  • Why not post the *complete* code? Where did you learn to remove necessary include directives etc? That's very ungood: often (though not in this case) the errors are caused by missing includes. Don't do that. Post complete code, please. – Cheers and hth. - Alf Aug 17 '18 at 14:11
  • Possible duplicate of [Exception in Destructor C++](https://stackoverflow.com/questions/42976461/exception-in-destructor-c) – Korni Aug 17 '18 at 14:11
  • @Korni: One of the *answers* there (the currently selected "solution") answers also this question, but that *question* is different, about nested exceptions. – Cheers and hth. - Alf Aug 17 '18 at 14:15

2 Answers2

6

Explanation from the MingW g++ compiler:

[P:\temp]
> g++ foo.cpp
foo.cpp: In destructor 'MyClass::~MyClass()':
foo.cpp:14:15: warning: throw will always call terminate() [-Wterminate]
         throw "invalid";
               ^~~~~~~~~
foo.cpp:14:15: note: in C++11 destructors default to noexcept

To really let it throw you can do this:

~MyClass() noexcept(false){
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Too bad MingW's error message isn't totally correct. Throwing an exception from a destructor results in calling `terminate()` if stack unwinding is underway (i.e. if the destructor is called due to another exception being thrown and not yet caught). If stack unwinding is not underway, throwing an exception from a destructor does not (necessarily) result in a call of `terminate()` - but it does cause other problems. – Peter Aug 18 '18 at 01:30
  • @Peter: You would be right for C++03. In C++11 and later, C++11 §15.4/9, "Whenever an exception is thrown and the search for a handler (15.3) encounters the outermost block of a function with an exception-specification that does not allow the exception, then, — if the exception-specification is a dynamic-exception-specification, the function std::unexpected() is called (15.5.2), — otherwise, the function std::terminate() is called (15.5.1).". The current standard is C++17. – Cheers and hth. - Alf Aug 18 '18 at 01:42
  • @Cheersandhth.-Alf - agreed. Although, even in C++17, someone going out of their way to throw an exception from a destructor, will probably also ensure that destructor has a throw-spec which allows that ..... (I realise that can discussion can get circular, but that's where my thinking was in the previous comment). – Peter Aug 18 '18 at 01:55
2

Since C++11 destructors are implicitly declared as noexcept documentation

non-throwing functions are all others (those with noexcept specifier whose expression evaluates to true as well as destructors, defaulted special member functions, and deallocation functions)

emphasis is mine.

Slava
  • 43,454
  • 1
  • 47
  • 90