p0llard p0llard - 15 days ago 7
C++ Question

Class pointer members and exception handling

Suppose we have a class like the following:

class A {
public:
A();
~A();
void foo();
int* pointer;
};

A::A() {
pointer = new int;
}

A::~A() {
delete pointer;
}

A::foo() {
throw "error";
}


And the following examples which utilise it:


Example 1


int main() {
A a;
throw "error";

return 0;
}



Example 2


int main() {
A a;
a.foo();

return 0;
}


In both of these cases, there will be a memory leak, as the destructor for A will never be called due to the unhandled exception.

My question is whether the responsibility lies with the user of the class to ensure the destructor is called by handling the exception: in the first example, the exception is unrelated to the class, so I would assume that the responsibility lies with the user of the class, but in the second example, the class itself is throwing the error - is it still up to the user of the class to ensure the exception is handled correctly, or is this simply bad design of the class itself?

Answer
void throw();

This is not going to compile. throw is a reserved keyword.

Ignoring this detail, for a moment, your initial assumption is not entirely true.

In this case, the exception is not caught and the program will terminate, so the memory leak is academic.

However, if there is a try/catch block in scope, that will catch the exception, there won't be a memory leak in either case. The a object was fully constructed, in both examples. As such, a thrown exception is going to destroy a, and invoke its destructor.

A thrown exception will unwind the stack until the exception is caught, and, as part of that process, destroy all objects in local scope, until the exception is caught.

So, this is a moot point. There is no memory leak, provided that the exception eventually gets caught, and nobody needs to worry about anything.

The class that you showed is mostly compliant with the RAII principle (needs a copy constructor and an assignment operator, to wrap up the loose ends). The only thing that class is responsible for would be if an exception is thrown in the constructor, whatever the constructor has allocated needs to be cleaned up.