Garbage collector collects live objects

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Mar 25 19:31:50 PDT 2015


On 3/25/15 9:51 AM, Ali Çehreli wrote:
> On 12/09/2014 08:53 AM, Steven Schveighoffer wrote:
>
>  > On 12/9/14 11:17 AM, ketmar via Digitalmars-d-learn wrote:
>
>  >> that file can be already finalized. please remember that `~this()` is
>  >> more a finalizer than destructor, and it's called on *dead* object.
>
> Agreed: D has a terminology issue here, what we call a "class
> destructor" is a "class finalizer". I have added D to the Wikipedia
> article:
>
>    http://en.wikipedia.org/wiki/Finalizer
>
> Now I want to improve some of my chapters.
>
>  >> here this means that any other object in your object (including
>  >> structs) can be already finalized at the time GC decides to call your
>  >> finalizer.
>
> Although I know the fact above, I think ketmar makes a distinction (that
> is new to me) that a finalizer is a function that does not reference
> class members but a destructor does (or safely can).

Think of it this way -- a D destructor can access data from it's own 
object. This means it CAN access its own members that are structs or 
value types. It should NOT access referenced data, unless that data is 
allocated outside the GC.

In Tango, there was a finalizer and a destructor. The finalizer was 
called from the GC. The destructor was called when using the 'delete' 
operator explicitly (and I think it also called the finalizer 
afterward). Having this informational structure helps to know where to 
put what cleanup code. I would love it if druntime added this feature, 
or something similar.

>
>  > File is specially designed (although it's not perfect) to be able to
>  > close in the GC. Its ref-counted payload is placed on the C heap to
>  > allow access during finalization.
>  >
>  > That being said, you actually don't need to write the above in the class
>  > finalizer, _file's destructor will automatically be called.
>  >
>  >> just avoid "destructors" unless you *really* need that. in your case
>  >> simply let GC finalize your File, don't try to help GC. this is not C++
>  >> (or any other language without GC) and "destructors" aren't destructing
>  >> anything at all. "destructors" must clean up the things that GC cannot
>  >> (malloc()'ed memory, for example), and nothing else.
>  >>
>  >
>  > Good advice ;)
>  >
>  > I would say other than library writers, nobody should ever write a class
>  > dtor.
>  >
>  > -Steve
>
> Can somebody elaborate on that guideline please. Given a case where
> runtime polymorphism is needed, so that we have to use classes, does the
> guideline simply mean that "arrange for manual cleanup" or is there more
> in that guideline? I am confused about the "library writers" part. :)

Destructors should only be used to clean non-GC resources (and in terms 
of completeness, you should implement such a destructor). It is 
important to remember that the GC may NEVER get around to calling your 
destructor. This means you cannot depend on it releasing non-GC 
resources in a timely manner.

A good example is a file descriptor. If you have an object that contains 
a file descriptor you SHOULD have a destructor which closes the file 
descriptor if not already closed. However, you should NOT technically 
rely on it being called in a timely manner. For cases where you can do 
it synchronously, use a specific method to close the file descriptor.

There is a school of thought that says it is an error to rely on the GC 
to destroy the FD, so why even have the destructor. But I see no reason 
to leak the FD out of spite.

This is why I say it should be only library writers -- they are the ones 
creating wrapper objects and using low level operations.

Of course, this isn't a hard and fast rule.

-Steve


More information about the Digitalmars-d-learn mailing list