Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ways to avoid memory leak when exception thrown

This is an exercise from C++ Primer, chapter 18:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    int *p = new int[v.size()];
    ifstream in("ints");
    // exception occurs here
}

The code above would cause memory leak, because the memory we manage directly (i.e. p) is not automatically freed when an exception occurs.

Exercise 18.3:

There are two ways to make the previous code work correctly if an exception is thrown. Describe them and implement them.

I know we can use smart pointer to avoid this pitfall:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    unique_ptr<int[]> p(new int[v.size()]);
    ifstream in("ints");
    // exception occurs here
}

or:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    shared_ptr<int> p(new int[v.size()], [](int *p){ delete[] p; });
    ifstream in("ints");
    // exception occurs here
}

I'm not sure if these are TWO ways. After all, they are the same virtually. So I thought of another way:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    int *p = new int[v.size()];
    ifstream in("ints");
    // exception occurs here
    if(!in)
        throw p;
}

// caller
try {
    exercise(b, e);
} catch (int *err) {
    delete[] err; // initialize err with b and delete e.
}

If exception occurs, throw p to initialize another pointer and delete that one. I know this is not a perfect solution, because other exceptions might occur so that I don't even have a chance to throw p. But I can't think of a better one. Could you help to find the second way?

like image 404
chihyang Avatar asked Dec 14 '15 02:12

chihyang


People also ask

What is the best way to prevent memory leaks when an exception is thrown?

By wrapping around the code and avoiding using "naked" resources, everything is based on the stack and the fact that those resources are going to be released for sure if an exception occurs.

What should be avoided to prevent memory leaks?

In summary, to avoid context-related memory leaks, remember the following: Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself) Try using the context-application instead of a context-activity.

Can exceptions cause memory leaks?

The pointer to the object goes out of scope when the exception leaves the function, and the memory occupied by the object will never be recovered as long as the program is running. This is a memory leak; it would be detected by using the memory diagnostics.


1 Answers

You can explicitly catch and re-throw the exception:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    int *p = new int[v.size()];
    try {
        ifstream in("ints");
        // exception occurs here
    } catch (...) {
        delete[] p;
        throw;
    }
    delete[] p;
}

Of course this doesn't work so well if you have multiple resources to free, because you may end up with nested try/catch blocks. Not to mention that you have two deletes for one new. So RAII is preferred.

like image 107
John Zwinck Avatar answered Oct 16 '22 21:10

John Zwinck