5

The following example leave a possible memory leak because the destructor doesn't run for the object on which the exception is handled during its constructor is run. where do i handle this memory leak?

#include <exception>

class MyClass {

public:
       MyClass() 
       {
           c = new char[5];
           throw std::runtime_error("test");
       }

      ~MyClass ()
       {
           delete[] c;
       }

private:
    char *c;
};

int main()
{
    try 
    {
        MyClass Obj;

    } 
    catch (std::runtime_error)
    {

    }
}
user103214
  • 3,478
  • 6
  • 26
  • 37

4 Answers4

6

Catch the exception in the constructor, tidy up (deallocate your memory), then throw the exception without the memory leak.

mskfisher
  • 3,291
  • 4
  • 35
  • 48
Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • The destructor was never called when i rethrow exception without memory leak in the constructor. is there any reason for this? – user103214 Oct 10 '11 at 08:03
  • 1
    @user974191: The object construction is not complete untill the ending brace of the constructor. Destructor is only called for Object which is complete. If constructor was not completely executed the object does not exist and hence no destructor will be called. – Alok Save Oct 10 '11 at 08:47
5

You are better off using RAII, smart pointer in this case to be specific.

Or alternatively, You can use Two Phased Construction strategy.

You could always use enclosing try-catch blocks inside constructor body and explicitly call delete for all those resources which you dynamically allocated but think of the scenario where you have n number of resources being dynamically allocated,it becomes really messy to explicitly keep track of each resource that you need to deallocate in the catch, in such a scenario, RAII provides you the best solution because then each resource implicitly takes care of its own deallocation and you do not need to have the overhead of keeping track of each resource.

boost::scoped_ptr or std::tr1::scoped_ptr are apt for this scenario instead of any raw pointers.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 2
    What calls for this downvote? RAII is the best way to go about this, and if someone says otherwise its incorrect.If you feel responsible to Downvote,feel responsible enough to explain us why? And if you cannot & just *feel* this is wrong then you are not qualified enough for downvoting, let someone else do that. – Alok Save Oct 10 '11 at 07:54
  • is this solution based on C++11 related stuff? – user103214 Oct 10 '11 at 08:08
  • 2
    Perhaps the downvote was for suggesting "two-phase construction"? That sounds like rather a bad idea to me. – Mike Seymour Oct 10 '11 at 10:33
4

One way is to throw the conditional exception in the beginning of the constructor and then allocate the memory.

  MyClass() 
  {
     if(<condition>)
       throw std::runtime_error("test");
     c = new char[<SIZE>];
  }

Other way is to use special try-catch() syntax enclosing the constructor:

MyClass() 
  try {
    c = new char[5];
    throw std::runtime_error("test");;
  }
  catch(std::runtime_error e) {
    delete[] c;
  }

Demo.

iammilind
  • 68,093
  • 33
  • 169
  • 336
1

You can catch the exception in the constructor body, do what cleanup you need, then rethrow the exception with throw;

That said, exceptions and manual handling of memory don't go nicely together. You will be much better off using an object that automatically manages the memory for the c member (e.g std::string, std::vector<char>, std::unique_ptr<char[]> etc). You really only need to manage memory explicitly if you are writing a class like one of the above whose purpose is exactly to look after that memory.

visitor
  • 1,781
  • 10
  • 7