Question

I was debating with some colleagues about what happens when you throw an exception in a dynamically allocated class. I know that malloc gets called, and then the constructor of the class. The constructor never returns, so what happens to the malloc?

Consider the following example:

class B
{
public:
    B()
    {
        cout << "B::B()" << endl;
        throw "B::exception";
    }

    ~B()
    {
        cout << "B::~B()" << endl;          
    }
};

void main()
{
    B *o = 0;
    try
    {
        o = new B;
    }
    catch(const char *)
    {
        cout << "ouch!" << endl;
    }
}

What happens to the malloced memory o, does it leak? Does the CRT catch the exception of the constructor and deallocate the memory?

Cheers!
Rich

Was it helpful?

Solution

A call to

new B();

resolves in two things:

  • allocating with an operator new() (either the global one or a class specific one, potentially a placement one with the syntax new (xxx) B())
  • calling the constructor.

If the constructor throw, the corresponding operator delete is called. The case where the corresponding delete is a placement one is the only case where a placement delete operator is called without the syntax ::operator delete(). delete x; or delete[] x; don't call the placement delete operators and there is no similar syntax to placement new to call them.

Note that while the destructor of B will not be called, already constructed subobjects (members or B and base classes of B) will be destructed before the call to operator delete. The constructor which isn't called is the one for B.

OTHER TIPS

When an exception is thrown from the constructor, the memory allocated by new is released, but the destructor of class B is not called.

In this case, your object, o, does not actually get constructed, and the memory allocated by new is freed. As such, the destructor does not get called. So you do NOT need to call:

delete o;

An interesting design pattern is RAII -- Resource Acquisition Is Initialization. In this pattern, you use a constructor to encapsulate the acquisition of a resource, and release the resource in the destructor. If the resource can not be acquired, you throw in the constructor -- much like your example. Thus if you have a valid object, you have the resource.

If the object is constructed, then you have successfully acquired the resource. This means that for the life of the object, you own the resource. When the object is deleted, the resource is released. If the object is never constructed, then you never acquired the resource. See wikipedia:

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

From the C++ 2003 Standard 5.3.4/17 - New:

If any part of the object initialization described above terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the new-expression. If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object’s memory to be freed. [Note: This is appropriate when the called allocation function does not allocate memory; otherwise, it is likely to result in a memory leak. ]

So there may or may not be a leak - it depends on whether an appropriate deallocator can be found (which is normally the case, unless operator new/delete have been overridden).In the case where there's a suitable deallocator, the compiler is responsible for wiring in a call to it if the constructor throws.

Note that this is more or less unrelated to what happens to resources acquired in the constructor, which is what my first attempt at an answer discussed - and is a question that is discussed in many FAQs, articles, and postings.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top