class someclass {};
class base
{
int a;
int *pint;
someclass objsomeclass;
someclass* psomeclass;
public:
base()
{
objsomeclass = someclass();
psomeclass = new someclass();
pint = new int();
throw "constructor failed";
a = 43;
}
}
int main()
{
base temp();
}
In the above code, the constructor throws. Which objects will be leaked, and how can the memory leaks be avoided?
int main()
{
base *temp = new base();
}
How about in the above code? How can the memory leaks be avoided after the constructor throws?
Yes, that code will leak memory. Blocks of memory allocated using "new" are not freed when an exception is raised. This is part of the motivation behind RAII.
To avoid the memory leak, try something like this:
Yes it will leak memory. When the constructor throws, no destructor will be called (in this case you don't show a destructor that frees the dynamically allocated objects, but lets assume you had one).
This is a major reason to use smart pointers - since the smart poitners are full fledged objects, they will get destructors called during the exception's stack unwind and have the opportunity to free the memory.
If you use something like Boost's scoped_ptr<> template, your class could look more like:
And you would have no memory leaks (and the default dtor would also clean up the dynamic memory allocations).
To sum up (and hopefully this also answers the question about the
statement):
When an exception is thrown inside a constructor there are several things that you should take note of in terms of properly handling resource allocations that may have occured in the aborted construction of the object:
This means that if your object owns resources, you have 2 methods available to clean up those resources that might have already been acquired when the constructor throws:
Everything you "new" needs to be deleted, or you'll cause a memory leak. So these two lines:
Will cause memory leaks, because you need to do:
In a finally block to avoid them being leaked.
Also, this line:
Is unnecessary. You just need to do:
Adding the "= base()" is unnecessary.
If you throw in a constructor, you should clean up everything that came before the call to throw. If you are using inheritance or throwing in a destructor, you really shouldn't be. The behaviour is odd (don't have my standard handy, but it might be undefined?).
you need to delete psomeclass... Its not necessary to clean up the integer...
RWendi
Both new's will be leaked.
Assign the address of the heap created objects to named smart pointers so that it will be deleted inside the smart pointers destructor that get call when the exception is thrown - (RAII).
Now psomeclass & pint destructors will be called when the stack unwind when the exception is thrown in the constructor, and those destructors will deallocate the allocated memory.
For ordinary memory allocation using (non-plcaement) new, memory allocated by the operator new is freed automatically if the constructor throws an exception. In terms of why bother freeing individual members (in response to comments to Mike B's answer), the automatic freeing only applies when an exception is thrown in a constructor of an object being new'ly allocated, not in other cases. Also, the memory that is freed is those allocated for the object members, not any memory you might have allocated say inside the constructor. i.e. It would free the memory for the member variables a, pint, objsomeclass, and psomeclass, but not the memory allocated from new someclass() and new int().