Arash
Arash

Reputation: 139

Throwing an exception in a constructor of a c++ class

Does the code below indicate memory leak?

The destructor of the Test class is not called (no output on the screen appears) and i'd assume all the memory allocated to the Int class array is not given back to the system? Is my assumption correct? How should I claim back resources allocated in a constructor if an exception occurs?

#include <iostream>
using namespace std;

class Int{
   public:
      int v;
      Int(){
        cout<<"inside Int constructor ..."<<endl;
      }

      ~Int(){
        cout<<"inside Int destructor ..."<<endl;
      }
};

class Test{
    public:
    Int* a;

    Test(){
        a=new Int[10];
        cout<<"inside Test constructor ..."<<endl;
        throw(0);
    }

    ~Test(){
      delete [] a;
      cout<<"inside Test destructor ..."<<endl;
    }
};

int main(){
   try{
      Test T;
   }
   catch (int e){
        cout<<"Error!!!"<<endl;
   }

    return 0;
}      

Upvotes: 2

Views: 1893

Answers (2)

Arash
Arash

Reputation: 139

I came up with a solution but not sure if this is a good design or right way to do it. could you comment?

#include <iostream>
using namespace std;

class Int{
    public:
    int v;
    Int(){
        cout<<"inside Int constructor ..."<<endl;
    }

      ~Int(){
        cout<<"inside Int destructor ..."<<endl;
    }
};

class Test{
    public:
    Int* a;

    Test(){
        try{
            a=new Int[10];
            cout<<"inside Test constructor ..."<<endl;
            throw(0); // exception is thrown
           }

         catch (int e){
               delete [] a;
               cout<<"Error!!!"<<endl;
           }
        }

    ~Test(){
      delete [] a;
      cout<<"inside Test destructor ..."<<endl;
    }
};

int main(){

      Test T;


      return 0;
}      

Upvotes: 0

C. E. Gesser
C. E. Gesser

Reputation: 821

The destructor is not invoked because the object was never fully constructed. Calling it on a partially contructed object could be more dangerous, as it would try to undo things that were never done. It is up to you, as a programmer, to ensure that no memory (nor any other resource) leaks from the constructor in case of exceptions.

But, the destructors of base classes and member variables will be called! That's why it is preferable in most cases to rely on smart pointers or containers, that will handle resource management for you. Try to change you class like this:

#include <memory>

class Test{
    public:
    std::unique_ptr<Int[]> a;

    Test(){
        a=std::make_unique<Int[]>(10);
        cout<<"inside Test constructor ..."<<endl;
        throw(0);
    }

    ~Test(){
      //no need to delete[] a;
      cout<<"inside Test destructor ..."<<endl;
    }
};

It is a win-win situation. You will see that the destructors of Int will be called, and you have no need to manually handle memory.

Upvotes: 2

Related Questions