Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-11-04 03:30:40


"E. Gladyshev" <egladysh_at_[hidden]> writes:

> --- David Abrahams <dave_at_[hidden]> wrote:
> [...]
>> Have you read the analysis section of
>> http://www.boost.org/more/generic_exception_safety.html?
>
> Sorry, my reply went to a wrong place. I revisited
> your article more carefully. Nice job!
> But I think it creates some very bad assumptions.
>
> 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(...) {} // ignore any exceptions above
> // print the vector's contents
> std::cout "(" << v.size() << ") ";
> std::copy( v.begin(), v.end(),
> std::ostream_iterator<X>( std::cout, " " ) );
> }
>
> Then we see the following statement!
>
> "Since all we know about v after an exception is that it is valid,
> the function is allowed to print any random sequence of Xs.3
> It is ``safe'' in the sense that it is not allowed to crash,
> but its output may be unpredictable."
>
> I don't see anything safe in this example.

It's not meant to be an illustration of safety. It's meant to
illustrate just what you can count on from the basic guarantee. It
is, however, perfectly safe for any reasonable definition of "safety".

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

> To fix the above code you need list all
> known exception types before catch(...).

Why do you think so?

> In catch(...), you just better do nothing.

Nothing *is* done "in catch(...)"

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

> There is supposedly another real-life example in this article:
>
> template <class T> // 1
> void SearchableStack<T>::push(const T& t) // 2
> { // 3
> set<T>::iterator i = set_impl.insert(t); // 4
> try // 5
> { // 6
> list_impl.push_back(i); // 7
> } // 8
> catch(...) // 9
> { // 10
> set_impl.erase(i); // 11
> throw; // 12
> } // 13
> }
>
> It sounds great in theory but if you use this
> technique, in practice, on real h/w and real OS,
> you'll make a false assumption that you are safe.

It relies on the same assumptions that any other portable C++ code
does. If you like, the catch(...) block can be replaced with an
automatic object's destructor, but that changes nothing as far as
standard C++ is concerned.

> This is how we can get the missle fired and start
> the next war. :)

I can think of lots of comebacks for that one, 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.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

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