Question

When a constructor of a class allocates memory on the heap, e.g.

class bla
{
    private:
        double *data;
        int size;

    public:
        bla(int s)
        {
            size = s;
            data = new double [size];
        }
        ~bla()
        {
            delete[] data;
        }
}

and I have a function e.g.

void f(bool huge)
{
    bla *ptr;
    if (huge)
        ptr = new bla(1e10);
    else
        ptr = new bla(1e2);

    //...

    delete ptr;
}

What happens if the allocation of ptr = new bla(1e10) is sucessful (this means, data and size allocated) but not the constructor -> he throws exception because 1e10 is to large? I have no memory leak with data = new double [size], but have I a memory leak with still existing double *data and int size on the heap? Or are they cleared by stack unwinding?

Should I write it better this way?:

void f(bool huge)
{
    bla *ptr = 0;
    try { ptr = new bla(1e10); }
    catch (...) { delete ptr; throw; }
}

and

class bla
{
    private:
        double *data = 0;
        // ... to not have an delete[] on a non-0 pointer
}

Edit:

A bit more elaborated example to illustrate templatetypedefs anwswer:

#include <iostream>

using namespace std;

class bla2
{
private:
    double *data;

public:
    bla2 ()
    {
        cout << "inside bla2 constructor, enter to continue";
        cin.get();
        data = new double [2*256*256*256];
    }
    ~bla2 ()
    {
        cout << "inside bla2 destructor, enter to continue";
        cin.get();
        delete[] data;
    }
};

class bla
{
private:
    bla2 data1;
    double data2[2*256*256*256];
    double *data3;

public:
    bla ()
    {
        cout << "inside bla constructor, enter to continue";
        cin.get();
        data3 = new double [8*256*256*256]; // when only 1/4 as much -> then all success
    }
    ~bla ()
    {
        cout << "inside bla destructor, enter to continue";
        cin.get();
        delete[] data3;
    }
};

void main()
{
    bla *a;
    cout << "program start, enter to continue";
    cin.get();
    try { a = new bla; }
    catch (...) { cout << "inside catch, enter to continue"; cin.get(); exit(EXIT_FAILURE); }
    cout << "success on a, enter to continue";
    cin.get();
    delete a;
}

Whit this example I can nicely see on my machine (Win7 4GB RAM) regarding the ressource monitor, how it goes first inside bla2() then bla() but then because because of failure allocating data3 first calls ~bla2() and then ends (without ~bla()) in catch(...) with memory being on baseline like at program start.

When I set the number of data3 elements only 1/4 as much, then all succedes, with expected order of call of constructors and destructors.

Was it helpful?

Solution

In C++, if an object created by new has its constructor throw an exception, then the language guarantees the memory allocated for the object proper will be deallocated. This means that you should not catch the exception and deallocate the memory, since the memory will already have been deallocated and you'll get undefined behavior.

If a constructor throws an exception, then the object's destructor will not be invoked. In your case, this isn't a problem - if the internal allocation fails, the memory reserved for the array will be cleaned up and the exception propagated outward. You don't need to do anything fancy. However, if you had multiple allocations, you would probably want to add exception handling inside the constructor to catch any allocation failures and deallocate appropriately.

However, there's a much easier solution: don't use new[] and delete[] to allocate the array. Instead, use std::vector, which handles all its own allocations and deallocations and requires no babysitting on your part. :-)

Hope this helps!

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