Boost logo

Boost :

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


--- 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. :)

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