Re: Exceptions in destructors
On Apr 29, 10:30 pm, Rennie deGraaf <degr...@cpsc.no-processed-
pork.ucalgary.ca> wrote:
Greg Herlihy wrote:
On 4/29/07 7:50 PM, in article f13lhq$f3...@ensb.cpsc.ucalgary.ca, "Rennie
deGraaf" <degr...@cpsc.no-processed-pork.ucalgary.ca> wrote:
I know that if an exception is thrown from a destructor while unwinding
the stack because of another exception, terminate() is called (FAQ
17.3). How exactly does this rule work? Is it acceptable to both throw
/and/ catch an exception inside a destructor, as in the following code?
So as long as the thrown exception in the code above is caught before Foo's
destructor exits, then terminate() will not be called. Therefore the above
code is technically safe - but it is also fragile. Specifically, Foo's
destructor assumes that finalize() will only ever throw a double - but
through there is nothing in finalize()'s implementation that enforces such a
restriction - nor is there anything in Foo's destructor to check whether its
assumption about the type of finalize()'s thrown exceptions - remains valid
since the last time it checked.
In other words, I really should add throw specifiers, like this:
struct Foo
{
void finalize() throw(double)
{
throw 1.0;
}
~Foo() throw()
{
try
{
finalize();
}
catch (double d)
{}
}
};
I suppose that it would generally be a good idea to /always/ tag my
destructors with throw() unless I have a good reason to do otherwise?
Personally, I would not bother adding throw() to destructor
declarations. The time and effort for making such a change would
probably be better spent making sure that no destructor in the program
propagtes exceptions beyond its scope.
On the other hand, the exception specification for finalize() I would
keep. Even though C++ exception specifications are checked at runtime
and not compile-time - at least the double exception specification
serves to document a dependency on finalize()'s thrown exception type
- that previously was not documented anywhere.
For that matter, are there any circumstances where it would be safe to
throw an exception from a destructor?
Sure - in fact I would imagine that under most circumstances throwing
an exception from a destructor would be safe. The problem is that
there are always circumstances when throwing an exception from a
destructor is not safe - so what should the program do instead?
In other words, it does not make a lot of sense for a program to throw
an exception - unless it is safe to throw that exception every time
the program wants to throw it. Otherwise, the code paths of the
program need to split into two different error-handling paths - one
when the exception is thrown and another when it is not. So throwing
an exception from a destructor does not end up simplifying or
consolidating the program's error handling - instead the two execution
paths just makes the program more complicated for no reason.
Greg