Topic: Exceptions and Destructors
Author: bglenden@colobus.aoc.nrao.edu (Brian Glendenning)
Date: 1996/02/15 Raw View
As I understand it, an object is only considered constructed when its
constructor has finished, so that an exception thrown from within that
constructor will not result in that object's destructor being
called. (Its completely constructed subobjects will be however).
What about the destructor? Is the object considered destructed when
the destructor is *entered*, or when it *completes*?
struct foo : public other
{
~foo {throw("BAD?");}
};
Since the above does not result in an infinite loop on the compilers I
have access to, I presume that the object is considered destructed
when the dtor is entered.
Questions:
Is this correct? Is it done this way to ensure in fact that infinite
loops like the above won't happen? How do resources in "other" get
released?
Thanks! -
Brian
--
Brian Glendenning - National Radio Astronomy Observatory
bglenden@nrao.edu Socorro NM (505) 835-7347
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. Moderation policy:
http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]
Author: David Byrden <100101.2547@compuserve.com>
Date: 1996/02/16 Raw View
>>> struct foo : public other
>>> {
>>> ~foo {throw("BAD?");}
>>> };
>> Since the above does not result in an infinite loop on the compilers I
>> have access to, I presume that the object is considered destructed
>> when the dtor is entered.
Compilers do not serve as a reliable definition of anything. The draft
C++ standard is available at http://www.cygnus.com/misc/wp/jan96 and
a query of it is less painful than a debugging session. :)
A quote:
15.3.10
The fully constructed base classes and members of an object shall be
destroyed before entering the handler of a function-try-block of a
constructor or destructor for that object.
I cannot easily find any other mention of when sub-objects are
destroyed during a destructor throw. I presume that somewhere it states
that they shall be destroyed, since you could always force their
destruction by writing a function-try-block with an empty handler.
I assume that you expected your infinite loop when a *stack* object is
destroyed, since the block in question then becomes subject to stack
unwinding. In fact, the object which threw is excluded from the
unwinding. This makes sense when you consider the situation of a block
that declares multiple local objects, and destroys them in reverse order.
If one of them throws, destruction of the whole lot does not start over
again.
It is generally not advisable to write destructors that throw. This can
lead to termination of the program when they do so during stack
unwinding, or when their object is a global.
David
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. Moderation policy:
http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1996/02/20 Raw View
Although the language doesn't mandate this, it's a good idea to obey the
rule: never, _never_, NEVER throw an exception from within a destructor.
If there's one operation that should be guaranteed to "work", it's
destroying an object. Remember that destructors are automatically called
during stack unwinding when an exception is thrown. If such a destructor
should throw another exception, what should happen? In fact, the
standard states that in this situation, terminate() will be called, and
terminate() is only one notch less violent than abort().
You can, of course, use exceptions _within_ a destructor, as long as you
handle them all. Just don't let them leak out, or you'll be hosed.
If an error might occur during destruction of an object, try to design
in a separate termination function that can be called first. For
instance, say you've got an object that represents an open file, and
destroying the object is supposed to commit any buffers and close the
file. What happens if a disk write occurs during the buffer writing?
The best approach is to design the destructor so that the error is
swallowed, to avoid violating the above rule. If you need to see the
error, supply a commit() member that can be called before destroying the
object, that will detect any disk errors and leave the file object in a
state that can be destroyed without causing any errors.
--
Ciao,
Paul D. DeRocco
---
[ To submit articles: Try just posting with your newsreader. 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
]