[rfc] fix libstdc++/10606
Benjamin Kosnik
bkoz@redhat.com
Wed Jan 5 01:24:00 GMT 2005
>> It all depends on what you consider uncaught_exception useful
>> for, I guess.
>
>When uncaught_exception() returns true, throwing an exception may
>(but isn't required to) cause the runtime to call terminate().
>When it returns false, throwing an exception is guaranteed not
>to cause a call to terminate (provided there's a handler for it,
>of course). This is useful in implementing the copy ctors of
>exception classes.
Also exceptions in dtors... there is standard-mandated usage for this already.
> From the table in core issue 475, requiring "0|1|1|1" as the
>proposed resolution suggests, means that either of "0|1|1|1|OK"
>and "0|1|1|1|ABRT" is permitted. Requiring "0|0|1|1" (which would
>be my preference) would mean that only "0|0|1|1|OK" would be
>allowed (i.e., no call to terminate() could happen during the
>construction of the [temporary] object to be thrown).
For the lazy among us, can you post the test code for constructing
that table please?
>Suppose "0|1|1|1" is required and you are implementing the copy
>ctor of an exception class. You'd have to code it along these
>lines for exception safety:
>
> struct B { /* third party non-exception class */ };
> struct M { /* third party non-exception class */ };
>
> struct S: B {
> M m;
> S (const S &rhs)
> try: B (rhs), m (rhs.m) { /* ... */ }
> catch (...) {
> if (std::uncaught_exception ()) {
> // what to do here?
> }
> else
> throw;
> }
> };
>
> try {
> throw S (); // can only throw S or call terminate()
> }
> catch (const S &s) { /* cannot throw */ }
> catch (...) { /* never reached */ }
Disaster....
>If, on the other hand, "0|0|1|1" were required, the copy ctor wouldn't
>have to worry about exceptions and could simply let them propagate to
>the caller. If an exception occurred while S was being thrown the new
>exception would simply displace S. A defensively written program won't
>catch exceptions by value so S won't have to worry about terminate()
>being called while the handler's exception object is being initialized.
>The code would look like this:
>
> struct S: B {
> M m;
> S (const S &rhs): B (rhs), m (rhs.m) { /* ... */ }
> };
>
> try {
> throw S (); // can throw S or anything else
> }
> catch (const S &s) { /* cannot throw */ }
> catch (...) { /* handle exceptions thrown from S::S(const S&) */ }
...compelling.
Also, this clarifies/simplifies uncaught_exception to something that
means true when an exception object (not temporary object) is "in
flight." I like that part.
-benjamin
More information about the Libstdc++
mailing list