Topic: Exceptions in destructors.
Author: Dick Menninger <Dick.Menninger@daytonoh.attgis.com>
Date: 1995/11/14 Raw View
> ==========Scott Meyers, 11/10/95==========
>
>
> >While trying to implement an exception-safe array class
(and model it
> >on the built-in C style arrays as closely as possible), it
occured to
> >me that the draft doesn't really have much to say about the case of
> >exceptions thrown in destructors. Two cases occur to me:
>
> > T a[ 5 ] ;
> >
> >When destructing the third element (for example), an exception is
> >thrown. Are the remaining elements destructed? I would say yes.
>
> I agree. "Stack unwinding" and "object unwinding"
> (destruction) are closely related. If during destruction
> an exception is thrown, destruction continues (provided
> there is a reachable handler)
>
> I'm inclined to disagree. How is destruction to continue? Suppose we
> have this:
>
> try {
> T a[5];
> }
> catch (...) {
> // do something here
> }
>
> Now suppose destruction of a[3] throws. Do we go to the handler? If
> so, do we then go back into the try block to try destroying the rest of
> a? What if the handler does a rethrow, and the exception is not
> caught for
> many stack frames. After handling the exception, there is no
context to
> return to to continue destroying a. I don't see how this can work.
>
> If we don't go to the handler when a[3] throws, what if a[2]'s
destructor
> also throws? Then we've got two active exceptions, and it's terminate
> time.
Although the wisdom of continuing the backward destruction
of the array may be quite suspect, it seems that 15.2 of DWP
gives compilers no choice but to do that. The danger seems
to be an inherent part of requiring exception handling
(including the destructor processing while unwinding) to be
exception-free. Part of the problem here is that there can be
an environmental thing for class T (or that particular array)
that puts destruction of the other instances into the same
exception case. If that is the case, the destructor for the
class has to do the initial catch and put the class into
a special state before rethrowing it. Further, the exception
instance has to deal with notifying class T on its "final"
destruction. If temporaries can get destroyed after copying
those are not "final" destructions. The notification would
take the class out of the special state if appropriate.
If the problem is not environmental to T, then you must take
your chances, but the DWP seems to say compilers better
continue with destruction of the array.
Good Day
Dick
Dick.Menninger@DaytonOH.ATTGIS.COM
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: Dick Menninger <Dick.Menninger@daytonoh.attgis.com>
Date: 1995/11/14 Raw View
> ==========Scott Meyers, 11/10/95==========
[snip]
> > T a[ 5 ] ;
> >
> >When destructing the third element (for example), an exception is
> >thrown. Are the remaining elements destructed? I would say yes.
[another agreement deleted]
> I'm inclined to disagree. How is destruction to continue? Suppose we
> have this:
>
> try {
> T a[5];
> }
> catch (...) {
> // do something here
> }
>
> Now suppose destruction of a[3] throws. Do we go to the handler? If
> so, do we then go back into the try block to try destroying the rest of
> a? What if the handler does a rethrow, and the exception is not
> caught for
> many stack frames. After handling the exception, there is no
context to
> return to to continue destroying a. I don't see how this can work.
>
> If we don't go to the handler when a[3] throws, what if a[2]'s
destructor
> also throws? Then we've got two active exceptions, and it's terminate
> time.
Although the wisdom of continuing the backward destruction
of the array may be quite suspect, it seems that 15.2 of DWP
gives compilers no choice but to do that. The danger seems
to be an inherent part of requiring exception handling
(including the destructor processing while unwinding) to be
exception-free. Part of the problem here is that there can be
an environmental thing for class T (or that particular array)
that puts destruction of the other instances into the same
exception case. If that is the case, the destructor for the
class has to do the initial catch and put the class into
a special state before rethrowing it. Further, the exception
instance has to deal with notifying class T on its "final"
destruction. If temporaries can get destroyed after copying
those are not "final" destructions. The notification would
take the class out of the special state if appropriate.
If the problem is not environmental to T, then you must take
your chances, but the DWP seems to say compilers better
continue with destruction of the array.
A related question is:
Does the DWP require the frames to be unwound
while it looks for a handler that catches the exception,
so that if it does not find a valid catcher all frames
are still gracefully undone (barring another exception)?
Good Day
Dick
Dick.Menninger@DaytonOH.ATTGIS.COM
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: smeyers@netcom.com (Scott Meyers)
Date: 1995/11/15 Raw View
In article <DI24xB.756@falcon.daytonoh.attgis.com> mennid <Dick.Menninger@daytonoh.attgis.com> writes:
| Although the wisdom of continuing the backward destruction
| of the array may be quite suspect, it seems that 15.2 of DWP
For non-heap arrays, the DWP does seems to say that. Is this reasonable?
| gives compilers no choice but to do that. The danger seems
| to be an inherent part of requiring exception handling
| (including the destructor processing while unwinding) to be
| exception-free. Part of the problem here is that there can be
| an environmental thing for class T (or that particular array)
| that puts destruction of the other instances into the same
| exception case. If that is the case, the destructor for the
I don't understand this at all. Can you elaborate?
| class has to do the initial catch and put the class into
| a special state before rethrowing it. Further, the exception
| instance has to deal with notifying class T on its "final"
| destruction. If temporaries can get destroyed after copying
| those are not "final" destructions. The notification would
| take the class out of the special state if appropriate.
|
| If the problem is not environmental to T, then you must take
| your chances, but the DWP seems to say compilers better
| continue with destruction of the array.
|
| A related question is:
| Does the DWP require the frames to be unwound
| while it looks for a handler that catches the exception,
| so that if it does not find a valid catcher all frames
| are still gracefully undone (barring another exception)?
The DWP makes it clear that stack frames need not be unwound if no handler
is found, but if a handler is found, locals in intervening frames must have
been destroyed by the time the handler is entered.
Scott
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: John Max Skaller <maxtal@suphys.physics.su.oz.au>
Date: 1995/11/09 Raw View
James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de> wrote:
>
>
>While trying to implement an exception-safe array class (and model it
>on the built-in C style arrays as closely as possible), it occured to
>me that the draft doesn't really have much to say about the case of
>exceptions thrown in destructors. Two cases occur to me:
>
>1. Given:
>
> T a[ 5 ] ;
>
>When destructing the third element (for example), an exception is
>thrown. Are the remaining elements destructed? I would say yes.
I agree. "Stack unwinding" and "object unwinding"
(destruction) are closely related. If during destruction
an exception is thrown, destruction continues (provided
there is a reachable handler)
>does the memory get freed
>(operator delete[] get called)?
>I can find nothing in the draft
>standard to indicate that it does, but if it doesn't, how does one go
>about freeing it later?
Good point. That kind of makes it necessary that
a scheduled dealloctation occur, despite any exception
thrown. As if:
delete p;
meant:
try { p->~P(); }
catch(...) {
operator delete(p);
throw;
}
operator delete(p);
[Smly for array case?]
--
John Max Skaller voice: 61-2-566-2189
81 Glebe Point Rd fax: 61-2-660-0850
GLEBE NSW 2037 email: maxtal@suphys.physics.oz.au
AUSTRALIA email: skaller@maxtal.com.au
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: smeyers@netcom.com (Scott Meyers)
Date: 1995/11/10 Raw View
>While trying to implement an exception-safe array class (and model it
>on the built-in C style arrays as closely as possible), it occured to
>me that the draft doesn't really have much to say about the case of
>exceptions thrown in destructors. Two cases occur to me:
> T a[ 5 ] ;
>
>When destructing the third element (for example), an exception is
>thrown. Are the remaining elements destructed? I would say yes.
I agree. "Stack unwinding" and "object unwinding"
(destruction) are closely related. If during destruction
an exception is thrown, destruction continues (provided
there is a reachable handler)
I'm inclined to disagree. How is destruction to continue? Suppose we
have this:
try {
T a[5];
}
catch (...) {
// do something here
}
Now suppose destruction of a[3] throws. Do we go to the handler? If
so, do we then go back into the try block to try destroying the rest of
a? What if the handler does a rethrow, and the exception is not caught for
many stack frames. After handling the exception, there is no context to
return to to continue destroying a. I don't see how this can work.
If we don't go to the handler when a[3] throws, what if a[2]'s destructor
also throws? Then we've got two active exceptions, and it's terminate
time.
thrown. As if:
delete p;
meant:
try { p->~P(); }
catch(...) {
operator delete(p);
throw;
}
operator delete(p);
[Smly for array case?]
Does this imply that for an array, you're suggesting the above code
(more or less) be put inside an implicit loop that cyles through each
member of the array? Doesn't the implicit catch(...) hijack any
client-provided exception handling?
As long as we're on the topic of exceptions in destructors, here's
another question. If a derived class destructor throws an exception, do
member and base class destructors still get called?
Consider this program:
#include <iostream.h>
class M {
public:
~M() { cout << "M destructor\n"; }
};
class B {
M m;
public:
~B() { cout << "B destructor\n"; }
};
class D: public B {
M m;
public:
~D() { cout << "Starting D destructor\n";
throw "Ouch!";
cout << "Ending D destructor\n";
}
};
int main()
{
D d;
return 0;
}
When d is destroyed, D's destructor throws. Are destructors
nevertheless called for D::m, the B part of d, and B::m? My feeling is
the answer should be no, in the same way that the remainder of D's
destructor is not executed after the throw. Different compilers do
different things, however. Who knows what is supposed to happen?
Scott
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>
Date: 1995/11/06 Raw View
While trying to implement an exception-safe array class (and model it
on the built-in C style arrays as closely as possible), it occured to
me that the draft doesn't really have much to say about the case of
exceptions thrown in destructors. Two cases occur to me:
1. Given:
T a[ 5 ] ;
When destructing the third element (for example), an exception is
thrown. Are the remaining elements destructed? I would say yes. The
words concerning partially constructed objects in 15.2 would seem to
sort of agree, but I would be happier if their was at least a footnote
to indicate that `partially constructed' objects also occur as a
result of partial destruction.
2. Given:
T* pa = new T[ 5 ] ;
// ...
delete [] pa ;
Again, an exception when destructing the third element of the array
pointed to by pa, in the delete expression. The above question is
obviously still valid, but in addition: does the memory get freed
(operator delete[] get called)? I can find nothing in the draft
standard to indicate that it does, but if it doesn't, how does one go
about freeing it later? (Calling operator delete[] directly is
illegal, since the pointer `pa' is not required to be, and often
isn't, the value returned by operator new[].)
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]