Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does destructor of a C++ class that throws an exception gets called?

Suppose I have a class like this:

#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 destructor ~Boda never gets called, thus the ptr resource never get freed.

Here is the output of the program:

terminate called after throwing an instance of 'int'
Aborted

So it seems the answer to my question is No.

But I thought that the stack got unwound when an exception got thrown? Why didn't Boda b object get destructed 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 Cydo.

like image 584
bodacydo Avatar asked Jun 27 '10 23:06

bodacydo


1 Answers

If the exception is not caught anywhere, then the C++ runtime is free to go straight to terminating the program without doing any stack unwinding or calling any destructors.

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

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

RAII means that dynamically (heap) allocated memory is always owned by an automatically (stack) allocated object that deallocates it when the object destructs. This relies on the guarantee that the destructor will be called when the automatically-allocated object goes out of scope, whether due to a normal return or due to an exception.

This corner-case behavior is normally not a problem with respect to RAII, since usually the main reason that you want the destructors to run is to free memory, and all memory is given back to the OS when your program terminates anyway. However if your destructors do something more complicated, like maybe remove a lock file on disk or something, where it would make a difference whether the program called destructors or not when crashing, you may want to wrap your main in a try-catch block that catches everything (only to exit on exception anyway) just to ensure that the stack always unwinds before terminating.

like image 138
Tyler McHenry Avatar answered Nov 14 '22 23:11

Tyler McHenry