Constructor exception in C ++

I read several articles here and also where it is normal to throw an exception from the constructor. However, I noticed that it does not call the destructor of the base class or its data members if an exception is thrown from the constructor. Consider the following example:

#include <iostream> using namespace std; struct C { C() { cout << __FUNCTION__ << endl; } ~C() { cout << __FUNCTION__ << endl; } }; struct E: public C { C c; E() { cout << __FUNCTION__ << endl; throw 4; } ~E() { cout << __FUNCTION__ << endl; } }; int main() { E e; } $ g++ test.cpp; ./a.exe C C E terminate called after throwing an instance of 'int' Aborted (core dumped) 

In this case, constructor E throws an exception, but C destructor as a data element or as a base class is not called. Now, if C destructor performs some cleanup operation, for example, closes files / sockets and removes heap allocation, this can cause problems.

So my question is why and when is it normal to throw exceptions from the constructors.

+8
c ++ constructor exception-handling
source share
4 answers

If you catch an error, the destructor will be launched. When an uncaught exception is thrown in C ++, the runtime calls std::terminate . By default, std::terminate calls std::abort , which does not specifically call output destructors.

In this version:

 #include <iostream> using namespace std; struct C { C() { cout << __FUNCTION__ << endl; } ~C() { cout << __FUNCTION__ << endl; } }; struct E: public C { C c; E() { cout << __FUNCTION__ << endl; throw 4; } ~E() { cout << __FUNCTION__ << endl; } }; int main() { try { E e; } catch(...) { } return 0; } 

I get the output:

 C C E ~C ~C 
+12
source share

I noticed that it does not call the destructor of the base class or its data members if an exception is thrown from the constructor

Yes it is.

However, since you do not catch this exception in the entire program, the program exits immediately.

If you were to catch an exception somewhere above the call stack, then the base class and member destructors will be called as expected.

+2
source share

You do not handle an "exception".

 > cat test.cpp #include <iostream> using namespace std; struct C { C() { cout << __FUNCTION__ << endl; } ~C() { cout << __FUNCTION__ << endl; } }; struct E: public C { C c; E() { cout << __FUNCTION__ << endl; throw 4; } ~E() { cout << __FUNCTION__ << endl; } }; int main() { try { E e; } catch (int i) { std::cerr << "Handled " << i << std::endl; } } 

Build and run.

 > make test make: `test' is up to date. > ./test C C E ~C ~C Handled 4 > 

Both C destroyed and have a perfectly normal completion.

+1
source share
 1) E constructor catched the exception and ran completly. Therefore, its object is created and the distructor is invoked. struct C { C() {cout <<__FUNCTION__<< endl;} ~C() {cout <<__FUNCTION__<< endl;} }; struct E: public C { C c; E() { try { cout <<__FUNCTION__<< endl; throw 4; } catch(int i) { cerr<<"int "<<i<<" is catched by "<<__FUNCTION__<<endl; } } ~E() {cout << __FUNCTION__ << endl;} void print(){ cout<<"obj of class E is created"<<endl; } }; int main() { try { E e; e.print(); } catch(int i) { cerr<<"int "<<i<<" catched by "<<__FUNCTION__<<" function"<<endl; } return 0; } /* Results: C::C C::C E::E int 4 is catched by E::E obj of class E is created E::~E C::~C C::~C */ 2) E constructor didn't catch the exception and ran incompletly. In result, its object is not created. Therefore, its distructor is not invoked. struct C { C() {cout <<__FUNCTION__<< endl;} ~C() {cout <<__FUNCTION__<< endl;} }; struct E: public C { C c; E() { try { cout <<__FUNCTION__<< endl; throw 4; } catch(float i) { cerr<<"int "<<i<<" is catched by "<<__FUNCTION__<<endl; } } ~E() {cout << __FUNCTION__ << endl;} void print(){ cout<<"obj of class E is created"<<endl; } }; int main() { try { E e; e.print(); } catch(int i) { cerr<<"int "<<i<<" catched by "<<__FUNCTION__<<" function"<<endl; } return 0; } /* Results: C::C C::C E::E C::~C C::~C int 4 catched by main function */ 
+1
source share

All Articles