[gclist] Destructor FAQ

Robert A Duff bobduff@world.std.com
Thu, 14 Mar 1996 08:22:31 -0500


> I would argue that we should distinguish between 2 concepts:
> 
> - destructors (a.k.a Ada "finalization")  These are basically actions invoked
> at predefined times when a variable goes out of scope.  These can safely be
> used for all sorts of things, including releasing locks, closing windows, etc.
> 
> - finalization (not Ada "finalization").  These are actions invoked
> asynchronously when the system determines that an object (usually in the heap)
> can no longer be accessed.  Useful only for non-time-critical resource...

I don't see why you want to make a big deal about this distinction.
Yes, finalization can be used in both ways, but I see no need for two
different language features.  (Integer data types can be used for
counting apples, or for counting oranges -- do we need two separate
language features?  ;-))

I also don't understand why you pick those two terms ("destructors"
vs. "finalization") -- I thought they were synonymous.  And I claim that
Ada's finalization can be used for both of the above, whereas you claim
it doesn't work for the second one (the one you call "finalization").
The semantics of Ada finalization and C++ destructors is very similar,
so it seems strange to draw a distinction between them.

It seems to me that the right approach is to define a latest point at
which finalization/destructors can happen.  For stack objects, this is
easy.  For heap objects, it might be defined as "just before program
termination", although as I said, Ada's definition is somewhat more
powerful.

Then define that for heap objects, the garbage collector is allowed to
do finalization earlier than the latest possible point, if it finds
garbage.

Now, it is true that if the programmer wants very explicit control, then
finalizable objects are going to have to be put on the stack.  Or a
finalizable object on the stack can explicitly invoke finalization of
heap objects.  But that doesn't mean that finalization of heap objects
is a completely separate language feature.  Should the garbage collector
be invoked when we run out of file handles, and should programs rely on
that?  Well, it depends on how scarce and/or expensive file handles are.
Seems like something that should be under programmer control, rather
than decided once and for all by a gc implementer.

As for cycles, yes that introduces a problem in choosing the
finalization order.  But that's inherent in finalization, and has
nothing to do with garbage collection.  Clearly, in the case of cycles,
one is going to have to rely on the programmer to somehow define the
order.  I think it's best to base this on the data types involved,
rather than requiring the programmer to explicitly break cycles at run
time.  I don't see any harm in letting a finalizer see an
already-finalized object -- if the programmer has cycles, then the
finalizer has to be written to take that into account.  A finalized
object is still in a well-defined state (maybe it has some nil pointers
in it) -- pointing to an already-finalized object is not a disaster like
a dangling pointer is.

- Bob