Boost logo

Boost :

From: E. Gladyshev (egladysh_at_[hidden])
Date: 2003-11-04 04:50:26


--- "E. Gladyshev" <egladysh_at_[hidden]> wrote:
>
> --- David Abrahams <dave_at_[hidden]> wrote:
>
> [...]
> > > It catches all exceptions, so there is nothing safe
> > > after that. I might be missing something but
> > > I think that it is creates a very bad impression
> > > that after you put catch(...), it is safe
> > > to use the object.
> >
> > Show me any C++ code you think is safe, and I will show you that your
> > claim of safety relies on all the same conditions.
>
> I think that the following code is much safer.
> The first precondition is that you have to know what
> exceptions a "correct" implementation of a class
> can possibly generate. Let's assume that
> that the correct method, my_type::f() can generate
> only one exception, out_of_memory and my_type
> provides basic guarantees.
>
> Then the safer code is
>
> my_type *p = new my_type
> try
> {
> p->f();
> }
> catch( out_of_memory ) //it is safe to use 'p'
> {
> delete p;
> }
> catch( ... ) //nothing is safe, don't use 'p'
> {
> exit(); //or throw; or while(1) {} just try to stop the execution here by any means
> }
>
>
> >
> > > To fix the above code you need list all
> > > known exception types before catch(...).
> >
> > Why do you think so?
>
> See the above, when you do catch(...), you are cathing
> all exception including the one that can be caused
> by incorrect program.
>
> >
> > > In catch(...), you just better do nothing.
> >
> > Nothing *is* done "in catch(...)"
>
> I think you know what I meant. You cannot use the object after catch(...)
> as in your example.
>
> >
> > > template <class X>
> > > void print_random_sequence()
> > > {
> > > std::vector<X> v(10); // A vector of 10 items
> > > try {
> > > // Provides only the basic guarantee
> > > v.insert( v.begin(), X() );
> > > }
> > > catch( out_of_memory ) {}// ignore any exceptions above
> > > catch( bad_mood ) {} // ignore any exceptions above
> > > catch(...)
> > > { //nothing is safe, run!
> > > }
> > > // print the vector's contents
> > > std::cout "(" << v.size() << ") ";
> > > std::copy( v.begin(), v.end(),
> > > std::ostream_iterator<X>( std::cout, " " ) );
> > > }
> >
> > That does exactly the same thing as my version. Maybe you should
> > check out Herb Sutter's "[More] Exceptional C++" books. They discuss
> > many of these issues in a tutorial fashion.
>
> Sorry, I meant
> catch(...)
> { //nothing is safe, run!
> return; //throw; exit()
> }
> The bottom line is that you cannot use 'v' anymore.
>
> [...]
> >
> > I can think of lots of comebacks for that one,
>
> Sorry, I was just kidding (it is not the first missle joke on this thread). :)
>
> > but instead let me
> > suggest that you make a good, careful study of the issues and consider
> > the full context of my article before you decide you know how to
> > handle exceptions more safely than the rest of us.
>
> What do you mean by "rest of us"?
>
> Thanks to this thread, I think that I can define
> safer exception handling techniques for myself.
>
> 1. If your method breaks an invariant internally and calls
> an outside method, make sure that you know all exceptions that
> a correct implementation of the outside method can generate.
> Catch the know exceptions *explicitly* and restore invariants.
> See the next item on what to do in catch(...)
>
> 2. If you call a method f() that provides basic guarantees,
> make sure to *explicitly* catch all exceptions that correct
> f() can possibly generate. It is possibly safe to continue
> the execution after a know exception.
> In the catch(...) block, assume that nothing is safe,
> use h/w interlocks or other system means to stop
> the execution immediately.
>
> This is what I would do to keep the missle in place. :)
>

Now, if we assume that in *real* life handling
exceptions *explicitly* is "safer" than catch(...),
we are in trouble with generic programming.
It will mean that as soon as you call a user
defined type/functor from a generic library,
in generic context, you don't know what exceptions
a correct implementation of this type can possibly
generate. So ideally every generic function should
expose exception handling policies or the best
the generic function can do is to catch all
exceptions (catch(...)) and use a system call
or other low-level means to stop the execution.
The low-level call can be defines as a policy as well.
So the claim that
"Interactions between templates and exceptions are
not well-understood." might after all be true
in opposite to what your article is suggesting.

Eugene

__________________________________
Do you Yahoo!?
Protect your identity with Yahoo! Mail AddressGuard
http://antispam.yahoo.com/whatsnewfree


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