[gclist] Finalization and death notices
Pekka P. Pirinen
Wed, 10 Oct 2001 14:49:29 +0100
| [Greg Colvin <email@example.com> wrote:]
| C++ completely decouples allocation, construction, destruction, and
| deallocation. You can call operator new(), constructors, destructors,
| and operator delete() directly.
That's almost, but not quite, true. The real problem is that delete *always*
calls the destructor. If the object has already been destructed, you're dead.
When is this not a bug in the program? Why would it have been already
destructed? Are you thinking of a collector that runs destructors on
objects that it reclaims, which would usually, but not always, have
been destructed (is that really a word?) already? In that case, I can
see a way around this:
You might think you could avoid this by having a flag set in your constructor
and cleared in you destructor - but that gives you undefined behavior: You
aren't allowed to look at the object once it's been destructed. Carrying the
flag in memory owned by the allocator but outside the object doesn't work
either - the destructor can't get at it, since it has no way to determine if
it's being called on a heap- or stack-allocated object, hence no safe way to
set the flag.
Just clear the flag in the deallocation functions (all four forms of
operator delete()); they know they're being called on a heap-allocated
object, so the flag can be stored outside the object. Then the
collector can look at the flag to decide whether it needs to call the
destructor, and the destructor doesn't need to know how.
I must admit we haven't implemented this.
Pekka P. Pirinen
Heard at OOPSLA 2000: We didn't pick the best solution [for the architecture],
because it would have required C++ programmers who understand the language.