Boost logo

Boost :

From: David Abrahams (david.abrahams_at_[hidden])
Date: 2002-01-14 20:23:54


----- Original Message -----
From: "terekhov" <terekhov_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Monday, January 14, 2002 7:29 PM
Subject: [boost] Re: first sight

> --- In boost_at_y..., "David Abrahams" <david.abrahams_at_r...> wrote:
> >
> > <<I mean that it is my understanding that "catch(...) without
> > throw;" is only valid if I am 100% sure that ALL exceptions
> > potentially thrown inside try block could be fully handled
> > by my catch(...) code (or I just terminate the process).
> > To me, it really does not happen too often, I even do not
> > remember the last time I wrote "catch(...) without throw;".
> > Do you have some really good example when it is deadly needed?>>
> >
> > Yes. Take a desktop editor application of some sort, with plugins,
> for
> > example. The application has an undo feature, so the first thing it
> does
> > before any editing operation is collect all the data it needs for
> rollback.
> > If the operation calls a plugin, the plugin might throw. We can't
> guarantee
> > that the plugin writer has translated all exceptions to types we can
> > recognize (even though we probably told her to), but we do know
> everything
> > we need to know in order to perform rollback and get back to a
> clean state
> > from which the user can save, print, whatever. A catch(...) is the
> only way
> > to be sure we get everything. From there we can tell the user there
> was an
> > unrecognized error and continue with the event loop.
>
> Well, maybe I am too paranoid (or it is just my
> poor brain being cloudy) but I would rather
> secure the data needed for rollback and would
> just restart in a clean new process invoking old
> process termination in catch(...) handler. Why
> should I trust anything in the old process when
> I observe an unexpected plug-in exception? Or
> am I missing something? Do you have any
> arguments against this approach?

Yeah: #1 you lose all of the user's data (I think?)
#2 Not every system has the ability to start up a new process at will (MacOS
9, Many embedded systems)
#3 Slow
#4 Confusing for users

But much more importantly, #5 - the type of the exception object almost
never changes anything about the correctness of your program state! All it
does is give you some information to use for user-friendly error reporting.
When was the last time you looked at the type of an exception and then took
a different recovery action than you would have otherwise, such that the
"otherwise" recovery would have put your program in a bad state if you
didn't do the special recovery? You'd have to have a situation like this:

The operation is documented as: "if an exception other than ReallyReallyBad
is thrown, there are no effects". In other words, in general you get the
strong guarantee, but in the special case that ReallyReallyBad is thrown,
you've only got the basic guarantee. So, there are two possibilities:

#1 It doesn't matter which guarantee you get. For example, the operation is
only modifying stack objects which will be destroyed upon unwind anyway.
Uninteresting.

#2 The operation modifies some important part of your program state which
you need to be able to recover. In other words, you need the strong
guarantee. Well, if you need the strong guarantee, it doesn't really matter
that the operation provides it most of the time: you need it all the time!
If you care about recovering from the possible ReallyReallyBad exception,
you have to prepare what's needed to restore your crucial program state
anyway, so you might as well write the recovery action once, assuming the
basic guarantee, and be done with it.

The point of all this is that it doesn't matter if the operation throws
ReallyReallyBad or any other exception, including ones whose name you don't
know: the recovery action is always the same, and is based on the
operation's exception guarantee. <language-bashing>That's why Java's focus
on always knowing the exception types at the expense of understanding what's
happened to the program state is so wrongheaded</language-bashing>, and
<opinion>why compiler-enforced exception-specifications are not nearly the
good idea that they seem to be at first</opinion>.

Yes, it's possible to design degenerate operations which break this model,
but there aren't too many of these around, even in legacy code. The
basic/strong/nothrow guarantees encourages a cooperative model where the
degenerate cases are even less likely.

[Wow, maybe I should write that book. I've never laid it out quite so
clearly before. At least, it sounds clear to me]

-Dave


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk