[gclist] Destructor FAQ

Robert A Duff bobduff@world.std.com
Fri, 15 Mar 1996 15:17:51 -0500


> This comment bothers me.  I could just as well say that it's the
> programmer's responsibility to make sure that they don't use pointers to
> discarded data and to make sure that all allocated memory is released when
> it is no longer needed.

There's a big difference between writing to a closed file, versus
following a dangling pointer.  The former has well-defined semantics
(raises an exception or whatever).  The latter can do arbitrary damage,
and can behave differently from one system to the next, or even from one
run of the program to the next.

>...However, one of the reasons I would like to use GC
> is that experience has shown that it can be extrememly difficult for the
> programmer to ensure that he has correctly done these things which are his
> "responsibility".  Further, we also know that when the programmer does not
> do this correctly, a program will tend to fail in strange and arcane ways
> that are difficult to track back to the original source of the problem.

But writing to a closed file is *easy* to track down, compared to
dangling pointer bugs.  Anyway, it's not possible to prevent *all* bugs.
What if I write:

    if ... then
        Close(File);
    end if;
    ...
    if ... then
        Write(File, X);
    end if;

?  No finalization in sight.  But it's impossible to know whether the
above writes to a closed file, without by-hand analyzing the 'if'
conditions.

> It seems to me that ordering of finalization falls in the same category. 
> The last thing I want to have to do is to try to find a bug relating to the
> fact that sometimes, probably depending on a lot of factors over which I
> have no control, my program fails in finalization because I'm writing to an
> already closed file.  And, as a programmer, what approach do I use to
> guarantee that the file will not be closed before I have a chance to flush
> the buffers.

But all these horrible problems everybody is worried about *only* occur
when you have cyclic dependencies.  I can't imagine why the file points
to the buffered-file.  The latter abstraction is built on top of the
former, and simple rules can choose the "right" order of finalization.

I still haven't seen an example of where cyclic and finalization need to
happen together, so maybe you're right to outlaw the combination.  But
it always makes me uneasy to outlaw things just because *I* haven't
thought of a use for them.

- Bob