4

Do I leak if I allocate memory with new in the constructor of an object and immediately after I throw an exception?

The object shouldn't be constructed at all and thus no destructor will be called, but what about that memory?

e.g.

MyObject() {
  data = new char[200]; // Will this be leaked?

  if(something_is_wrong)
    throw exception();

}
user129506
  • 337
  • 2
  • 10

4 Answers4

4

It will leak. Once you have gotten a pointer from new it eventually needs to be deleted. The solution is to make data a smart pointer (or in this case, probably a std::string); while MyObject's destructor won't be called, data members' destructors are called.

Simple
  • 13,992
  • 2
  • 47
  • 47
2

Yes, it will be a leak unless data is kind of handle, smart pointer and not a raw pointer char* data. A safe variant of this is:

class MyObject {

        std::vector<char> data; // or some handle/smart pointer (i.e. unique_ptr)
                                // it might be just std::string
    public:
        MyObject( int sz) : data( sz) {}
};

In this case the memory used is now managed by vector. You can of course do it by yourself what is actually done in vector already and is exception safe. This is you can use approach similar to std::uninitialized_fill.

4pie0
  • 29,204
  • 9
  • 82
  • 118
1

Unless data is a smart pointer (or, more generally, any object that frees the memory passed to it when it destructs) you will leak memory.

The new will need to be balanced with a delete[] (note the []). It's important to note that, since a MyObject instance was not created, the destructor to MyObject will not be called so you cannot rely on any memory cleanup there.

Two alternatives.

  1. free the memory before the throw statement.
  2. Make data a smart pointer (if it isn't already).

2 is preferred - by exploiting RAII it makes code more stable.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

The situation that you sketch,

MyObject() {
  data = new char[200]; // Will this be leaked?

  if(something_is_wrong)
    throw exception();

}

will1 leak unless automatic garbage collection is used (and even so it may still leak).

This case is very easily dealt with by using an appropriate standard library container:

MyObject()
{
  string data( 200, '\0' );
  if(something_is_wrong)
    throw exception();
}

And in general preferentially use standard library containers instead of all this new'ing, and if there isn't a suitable container, use smart pointers such as std::unique_ptr.

In short, there's not really a problem, not any more than a call to std::terminate is a problem (just remove the call, or don't do it in the first place).


However, if you define a custom allocation function for the class, and forget to define a corresponding deallocation function, then throwing an exception from a constructor can leak memory.

As a learner simply don't define allocation functions.

As a professional remember to do it properly if at some time you should really need it.


1) Under the reasonable assumption that you're not using a smart pointer to guarantee cleanup and asking this question without mentioning the smart pointer.
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331