Is a C ++ class destructor called that throws an exception?

Suppose I have a class:

#include <iostream> using namespace std; class Boda { private: char *ptr; public: Boda() { ptr = new char [20]; } ~Boda() { cout << "calling ~Boda\n"; delete [] ptr; } void ouch() { throw 99; } }; void bad() { Boda b; b.ouch(); } int main() { bad(); } 

It seems that the ~Boda destructor is never called, so the ptr resource is never freed.

Here is the result of the program:

 terminate called after throwing an instance of 'int' Aborted 

So it seems that the answer to my question is No

But I thought the stack was unwound when an exception was thrown? Why was the Boda b object not destroyed in my example?

Please help me understand this resource problem. I want to write better programs in the future.

Also, is this the so-called RAII ?

Thanks, Boda Sido.

+6
c ++ destructor resources
source share
3 answers

If the exception is not caught anywhere, then the C ++ runtime can freely proceed to the end of the program without performing a single stack unwinding or calling any destructors.

However, if you add a try-catch block around the call to bad() , you will see a destructor for the called Boda object:

 int main() { try { bad(); } catch(...) { // Catch any exception, forcing stack unwinding always return -1; } } 

RAII means that distributed memory with dynamic (heap) always belongs automatically (to the stack) to the allocated object, which frees it when the object is destroyed. It depends on the assurance that the destructor will be called when the automatically assigned object goes out of scope, due to a normal return or due to an exception.

This root mode behavior is usually not a problem with RAII, since usually the main reason you want destructors to start is free memory, and all memory is returned to the OS when your program terminates anyway. However, if your destructors do something more complicated, for example, perhaps delete the lock file on the disk or something like that, where it matters whether the program is called destructors or not when it fails, you can wrap your main in try -catch block that catches everything (only to exit the exception anyway) to make sure that the stack always unwinds before exiting.

+8
source share

The destructor will not be launched if an exception occurs in the constructor.

It will be triggered if necessary (if the exception is handled somewhere) if the exception is raised in another method, for example, in your example. But as the program ends, the call to the destructor is not needed here, and the behavior depends on the compiler ...

The idea of RAII is that the constructor allocates ressources, and the destructor frees them. If an exception occurs in the constructor, there is no easy way to find out which resources were allocated and which were not (this depends on the exact place in the constructor where the exception occurred). You should also remember that if the constructor fails, the only way to tell it to cause it to throw an exception and the allocated memory is freed (stack unwinding or allocated heap memory) as if it had never been allocated.

The solution is obvious: if any exception can occur inside the constructor, you should catch it and release the allocated resources if necessary. In fact, this may be some kind of duplicate code with a destructor, but this is not a big problem.

In the destructor, you should not raise exceptions, as this can lead to big trouble with erasing the stack.

In any other method, use exceptions as you like, but remember to handle them somewhere. An unhandled exception can be worse than an exception in general. I know some programs that do not handle exceptions for some minor errors ... and crash due to errors that should give a warning.

+2
source share

Try to clear the stream - you will see that the destructor is really called:

 cout << "calling ~Boda" << endl; 

This is I / O buffering that delays the printout until the end of the program before the actual exit.

Edit:

The above actions are performed for processed exceptions. With unhandled exceptions, the standard does not indicate whether the stack is unlocked or not. See also this SO question .

+1
source share

All Articles