Topic: exceptions in std lib


Author: "Nathan Myers <ncm@cantrip.org>" <ncm@cantrip.org>
Date: 1996/04/16
Raw View
James Kanze US/ESC 60/3/141 #40763 wrote:
>
> In article <316F646D.552DF1DD@cantrip.org> "Nathan Myers
> <ncm@cantrip.org>" <ncm@cantrip.org> writes:
> |> Bad things happen if you throw during copy construction or destruction
> |> of a vector element.

> Does this imply that `vector< string >' is unsafe.

That's debatable.  I think the Library WG expects that most
implementations will guarantee that copying strings doesn't throw,
though no such a guarantee is required by the standard.

It *does* imply that for `vector< deque<int> >', operations that
require reallocation in the vector could trigger exceptions
when copying the deque<int> container objects, leaving the vector
in an undefined state -- that is, it's not safe to call the
destructor.  For a vector on the stack, this would be pretty bad:
you would not be able to recover, or terminate the program normally.

> |> Don't let it happen.  (Yes, I know this is easier
> |> said than done.  Still.)   There are lots of things in the library that
> |> could break if a user object (or even a standard object!) throws during
> |> a standard function.

> If I understand what you are saying correctly, we should not use
> exceptions with the standard library, because it will not be required
> to be exception safe.

I'm just talking about the current state of the Draft.  Yes, it
is as bad as it sounds, and will be until somebody figures out
what to do about it and writes up a sound proposal.

Before you criticize this, consider what you would expect vector<>
to do when it is copying a block of elements from one memory region
to another, or deleting a block of elements, and an exception happens
in the middle.  Do you stop there, half-done?  Do you copy or delete
the rest of the elements and leave a hole, then rethrow?  (What if you
get another exception while doing the rest?)

If you propagate the exception, member functions of the vector (including
the destructor) will probably be called later.  What will they find?

This is a long way of asking: What do you mean by `required to be
exception-safe'?  If you can define it, then probably the standard
library ought to meet the definition.  If you *can't* define it,
then (at least) you will then need to be careful about what you put
in a vector.  Pointers & PODs are OK.

Nathan Myers
ncm@cantrip.org


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Wil Evers" <wil@ittpub.nl>
Date: 1996/04/17
Raw View
In article <317326BE.246CF449@cantrip.org> Nathan Myers <ncm@cantrip.org>
writes:

> Before you criticize this, consider what you would expect vector<>
> to do when it is copying a block of elements from one memory region
> to another, or deleting a block of elements, and an exception happens
> in the middle.  Do you stop there, half-done?  Do you copy or delete
> the rest of the elements and leave a hole, then rethrow?  (What if you
> get another exception while doing the rest?)
>
> If you propagate the exception, member functions of the vector
> (including the destructor) will probably be called later.  What will
> they find?
>
> This is a long way of asking: What do you mean by `required to be
> exception-safe'?  If you can define it, then probably the standard
> library ought to meet the definition.

It seems to me that Harald Mueller's article in the January '96 issue of
The C++ Report could be a big conceptual help here. Basically, after an
operation on an object has reported an exception, one of three things can
be true:

1. The object is in the state it was before the operation that reported the
exception was tried ('throw and keep'). IMHO this should be the default for
standard library components.

2. Futher operations on the object do not make sense, but it is still
possible to destroy it ('throw and throw away'). For some operations, it
may be impossible or practically infeasible to impose rule (1). Here, the
standard could require the operation's documentation to explicitly state
that this is the case. (Since the only sensible thing we can do with such
an object is to destroy it, the standard could also require that a standard
library object in such a state must throw an exception on every attempted
operation until it is destroyed.)

3. The object is in such an unstable state that it is not even possible to
destroy it. This should never happen. (Note: this implies that exceptions
should never escape from destructors.)

Of course, 'exception unsafety' is a cascading problem. It wouldn't make
much sense to require a template taking an argument of a type T to be
throw-and-keep if some of T's operations it depends on are
throw-and-throw-away.

- Wil
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]