Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clean initialized resources if exception thrown from constructor in c++

Some day before I faced this question in a interview. So just guide me.

How to clean initialized resources if exception thrown from constructor in c++?

like image 890
Johny_sa Avatar asked Oct 04 '12 08:10

Johny_sa


4 Answers

The trick is to use RAII(resource acquisition is initialization) to manage resources.

If you have pointer members then use smart pointers instead of raw pointers which will automagically do the cleanup job once a exception is thrown from constructor.

Good Read:
Herb Sutter's excellent GotW article "Construction Failures"

like image 114
Alok Save Avatar answered Nov 07 '22 04:11

Alok Save


When an exception is thrown the stack is unrolled up to the catch point. As a consequence everything had been constructed in it is destroyed.

The point is, so, wrap every sensible resource into a class whose destructor takes care of the disposing of the associated resource.

If the resource is an heap allocated object, smart pointers do exactly that (delete the pointed object upon thair destruction), if the resource is an open file a stream closes it upon destruction. Everything else requires a custom wrapper.

But note the many "resources" are represented by handlers that are themselve void*. This enables to use smart poitner as well, by initializing then with the allocated resoure and specifying a deleting function.

What the technique plays better is much more a matter of taste and opportunity.

like image 30
Emilio Garavaglia Avatar answered Nov 07 '22 06:11

Emilio Garavaglia


The best way to do it is: Allocate any resources in the constructors and deallocate any in the destructors.

Templates in C++ are very helpful for this purpose as we can make object creation atomic.

like image 1
Sasi Srinivas Avatar answered Nov 07 '22 06:11

Sasi Srinivas


Use data members that free the resources when they are destroyed (aka RAII).

For example:

struct TwoStrings {
    std::string string1;
    std::string string2;
    TwoStrings(const std::string &input) : string1(input) {
        if (!input[1] == ':') {
            throw std::logic_error('not a Windows absolute path');
            // yes, absolute paths can begin \\, this is a toy example
        }
        if (input.back() == '\\') {
            string2 = input;
        } else {
            string2 = input + "\\";
        }
    }
};

If the constructor throws (either logic_error or bad_alloc), then the already-initialized data member string1 is destroyed, freeing the resource. For that matter string2 is also destroyed, but if the constructor throws then string2 must still be empty, so that has no particular effect.

string is an example of a class that manages resources, but there are many others. The most flexible of them are called "smart pointers", and can be configured to manage pretty much any resource, not just self-allocated arrays of characters like string does.

like image 1
Steve Jessop Avatar answered Nov 07 '22 06:11

Steve Jessop