Re: Exception in Constructor
Am Sonntag, 16. September 2012 09:45:32 UTC+2 schrieb Henry:
[..]
http://www.parashift.com/c++-faq/ctors-can-throw.html
It says, "if a constructor finishes by throwing an exception, the memory
associated with the object itself is cleaned up ? there is no memory leak".
However, as I know (and I tested), when an exception is thrown inside a
constructor, the destructor won't be called.
[..]
It doesn't seems to me that "if a constructor finishes by throwing an
exception, the memory associated with the object itself is cleaned up ?
there is no memory leak" is true.
The statement from parashift.com is partly true, partly misleading at best.
The destructor is not called and parashift does not claim so. Your observed
behavior is what should happen.
The memory occupied by the object itself is released, so in this regard
parashift is right, too. - If this is not what you observe, its a compiler
bug IMHO.
However, there still is a memory hole, and this is where the site is
making too bold a statement. Allocations made by "new" in the constructor
are not tracked and there is no way to release it lacking a Java/.NET like garbage collected memory model.
A destructor call would not help since it got presented a halfway
constructed object only. It would pose a problem how to handle a
non-zero pointer member - is it non-zero because an allocation was
executed successfully or because it was not yet zeroed out?
External resource allocation may be even more difficult if you cannot
check for success if the return value is not yet stored by the allocating
routine (was the file opened or not before the exception?).
If there is a chance code in a constructor with dynamic allocation
generates an exception, I recommend to catch any inside the constructor
itself individually and releasing all such resources before re-throwing
the exception.
E.g:
class A {
private:
char* cstr1;
char* cstr2;
char* cstr3;
public:
A() {
cstr1 = new char[1000]; // no need to catch here,
// no cleanup on fail
try {
cstr2 = new char[1000000]; // may fail
}
catch ( std::bad_alloc ) {
delete cstr1;
throw;
}
try {
cstr3 = new char[1000000]; // may fail
}
catch ( std::bad_alloc ) {
delete cstr1;
delete cstr2;
throw;
}
}
};
I prefer this over nested try..catch even if it means
(minor) code duplication. The point is to leave behind
an object that only needs to have its own memory released
on exception.
best,
MiB.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]