[gclist] Destructor functions and GC

David Petrie Stoutamire davids@ICSI.Berkeley.EDU
Tue, 12 Mar 1996 18:43:20 -0800 (PST)


Hans said:
>In my mind, the real issue isn't this example, but whether or not it's possible
>to give the programmer clean rules for writing correct code.  If you don't have
>ordering guarantees, it seems to me that you violate abstraction boundaries all
>over the place.  The file buffer contains a file handle.  It shouldn't have to
>know whether or not that's a magic integer, or a pointer to another object or
>whether the other object has finalization enabled.  If you don't ensure proper
>ordering, you're saying that the finalization code may access certain fields
>but not others, and which fields may be accessed depends on implementation
>internals for those fields.
>
>As Charles points out, imposing the ordering constraint doesn't completely
>avoid the problem.  There are still cases in whcih you have to put more stuff
>in the interfaces than you would like.  But those cases are even less frequent.
>And if you ignore the problem you get an easily detectable leak instead of
>incorrect results or a crash.

I don't understand the abstraction boundary argument in this example.
Whether or not the file handle is closed manually or finalization is
used, there is a clear relationship between the buffers and the file
handle, which together are implementing an abstraction (eg. stream).
The file handle has to know about the buffers in the sense that the
buffers have to be flushed before the file handle is closed, and the
buffers have to know about the file handle in the sense that they use
it when they fill up.  So it's no big loss of encapsulation to have the
finalization code, whatever it is, obey the same rules that explicit
closing code would have had to follow.

I suspect I'm missing your point, because I don't see why you say this
has anything to do with whether the file buffer knows about the
internal representation of file handles.  Doesn't the encapsulation
argument work the opposite way?  If the programmer has to reason about
the heap topology (ie. acyclicity) to write correct finalization code,
then you are _requiring_ the abstraction violation.  If there aren't
finalization ordering guarantees based on pointer structure, this
doesn't come up.

I don't understand the crashing argument either.  Where are crashes
coming from?  I'm been talking about a system where deallocation (as
opposed to finalization) never occurs while an object is reachable,
even after finalization, so pointers are always valid.  Are you talking
about something other than dangling pointers?

I'm getting the impression that there is a fundamental miscommunication
here.  I find myself agreeing with all your points - for example, that
programmers must be given clean rules for writing correct code, and
that finalization should not violate abstraction boundaries - but then
I reach entirely different conclusions.  Perhaps we're just coming at
it from very different camps; I'm been deliberately ignoring the needs
of a finalizer meant to coexist with C++ destructors - useful though
such a thing may be.

Pardon my late response, I inexplicably stopped getting the list when I
switched over to gclist-digest, and am replying cut-and-paste from the
archives.

    - Dave

--
David Stoutamire
http://www.icsi.berkeley.edu/~davids