Topic: Exceptions in derived class destructors
Author: John Max Skaller <maxtal@suphys.physics.su.oz.au>
Date: 1995/11/25 Raw View
clamage@Eng.sun.com (Steve Clamage) wrote:
>Dick Menninger <Dick.Menninger@daytonoh.attgis.com> writes:
>
>You can exit a destructor via an exception safely only if you know
>that no exception is in the process of being handled, or if you
>know that the current object is not auto.
I do not believe the latter case is permitted.
I understand that an attempt has been made to
allow a caught exception (dynamically)
in the body of a destructor, but as far as I can
see this attempt has failed (I certainly
haven't seen a coeherent model for this
presented in a paper).
(that is, the working paper either contradicts itself
at present, or is terminologically muddled, or both :-)
--
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: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/21 Raw View
smeyers@netcom.com (Scott Meyers) writes:
>I posted this a while ago as part of a larger posting, but nobody ever
>responded. I'm reposting it as a separate question in hope of gaining
>insight into the proper behavior of destructors when exceptions are thrown:
>
> If a derived class destructor throws an exception, do member and base
> class destructors still get called?
If you are asking about what the current working paper says, I'm not sure
off-hand. If you are asking about what the working paper *should* say,
then I think the answer should be yes, member and base class destructors
should still get called. Otherwise the destructor would have to catch
execptions and manually destroy the bases and members before rethrowing
to avoid resource leaks. This would be extremely tedious coding,
and would be extremely difficult - probably totally impractical - in the
case of virtual inheritence.
> 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.
I disagree. The answer should be yes, in the same way that bases
and members are destroyed if an exception occurs in the constructor.
Any class which attempts to manage more than one resource must be
careful do its own recovery if an exception occurs after constructing
or destroying a subset of those resources. But for a class which
merely aggregates different resources which are managed by members or
base classes, the author of that class should not have to worry about
exception handling.
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
---
[ 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/22 Raw View
> ==========John Max Skaller, 11/20/95==========
> What's more, the committee has taken special pains to
> add an extensions late in the process to ensure
> memory can be deallocated correctly if a constructor
> invoked by a new expression fails. So called "placement
> delete" now exists to enable leak proof programs
> to be written. In addition, there is a flag for checking
> if there is a current unhandled exception, for the
> same reason -- so you can avoid throwing an exception
> (which would otherwise cause immediate termination,
> not a suitable action in some embedded or
> continuously running systems).
Such a flag can be of limited help, given the current
rules about only one exception at a time. But that is
a bandaid rather than a real solution to the fact that
multiple exceptional conditions do, in practice, overlap
in the real world situations. When you allow only one,
the first one to go off is it and you either completely
suppress the other exceptions which may be more serious
and need different handling at each catch level, or
you must do your own real mechanism that records
the real world multi-exception track behind the
exception mechanism's back while using one exception
as a token to get the frames and catch layers
unfolded. That may require you to encase "outside"
stuff to convert to your scheme. Has anyone gone
this route to an extent that would provide useful
fodder for the standard, or am I likely to forge
new paths if I get the kind of work I speculate
may be in the offing in the near future (I am a trailing
spouse and am about to find myself in a new situation)?
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: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/23 Raw View
clamage@Eng.sun.com (Steve Clamage) writes:
>smeyers@netcom.com (Scott Meyers) writes:
>
>> When d is destroyed, D's destructor throws. Are destructors
>> nevertheless called for d.D::m, the B part of d, and d.B::m? My feeling is
>> the answer should be no, ...
>
>The draft says that when an exception is thrown, control is transferred
>to the handler for that exception, or to the terminate function if
>there is no handler.
>
>I don't see how to interpret that to allow any additional processing if
>the destructor exits via an exception.
Yes, it does say that in 15.1, but it also says in 15.2 that
as control passes between those two points, stack unwinding happens -
destructors get called. Additional processing most definitely does occur!
>The special cases of operator new or a constructor exiting via an
>exception as part of a new-expression has some additional handling,
>but I don't see any special cases for destructors.
It's not a special case, it is just the usual case of stack unwinding.
See 15.2:
| 15.2 Constructors and destructors [except.ctor]
|
| 1 As control passes from a throw-point to a handler, destructors are
| invoked for all automatic objects constructed since the try block was
| entered.
Note - it does NOT say "for all automatic *complete* objects".
Note that according to the definition in 1.6 [intro.object], a
sub-object is an object. So it must include sub-objects.
In other words, according to the above quote from the April draft, base
class and member sub-objects that have been constructed since the try
block was entered should be destroyed.
Certainly the draft could be clearer - but it *is* only a draft.
>Apart from all of that, it is unlikely to be a good idea to throw
>an exception from a destructor. It would be safer and less likely
>to leave the program in an unknown state to use some other error-
>reporting method for destructors.
Agreed.
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
[ 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/18 Raw View
I posted this a while ago as part of a larger posting, but nobody ever
responded. I'm reposting it as a separate question in hope of gaining
insight into the proper behavior of destructors when exceptions are thrown:
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.D::m, the B part of d, and d.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. ]