Reputation: 187
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?
Upvotes: 6
Views: 903
Reputation: 249093
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 delete
s for one new
. So RAII is preferred.
Upvotes: 4