Destructors vs. Finalizers

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Wed Jul 26 17:00:08 PDT 2017


On 7/26/17 7:28 PM, Moritz Maxeiner wrote:
> On Wednesday, 26 July 2017 at 22:33:23 UTC, Steven Schveighoffer wrote:
>> On 7/26/17 2:33 PM, Moritz Maxeiner wrote:
>>> On Wednesday, 26 July 2017 at 17:38:28 UTC, Dgame wrote:
>>>> I don't get it. The GC collects the objects which aren't in use 
>>>> anymore. The order in which this is currently happening is not 
>>>> specified. So, how are the destructors supposed to be called in the 
>>>> right order? Manually? ARC?
>>>
>>> After the split:
>>> Destructors are only for deterministic end of object lifetime, so 
>>> yes, they are to be called by any scheme (such as manual management 
>>> via destroy and reference counting - which is likely also implemented 
>>> as calling destroy) that is deterministic.
>>> Finalizers are for nondeterministic schemes such as the GC.
>>> The GC *never* calls destructors directly, only finalizers.
>>> A finalizer might manually call a destructor, but a destructor may 
>>> never call a finalizer.
>>
>> Actually, it's the opposite.
> 
> It's a matter of definition and this is the behaviour I would define, 
> because
> 
>> A finalizer can never call anything on its members because it doesn't 
>> know if it's being destroyed by the GC.
> 
> This falsely assumes that all members point into the GC pool.

Yes, I should have qualified GC members.

> A 
> finalizer may freely work on non-pointer members and pointer members 
> that target objects outside the GC pool which the programmer knows to be 
> valid at finalization (e.g. they are manually managed).
> Whether or not it makes sense for the finalizer to call the destructor 
> is something the programmer has to decide on a per use case basis.

No, because a destructor can safely assume it can look at GC members' 
data. So a finalizer can never call it.

>>
>> The destructor is ensured that the entire structure is intact, so it 
>> can do whatever it wants.
> 
> The point is that I saw (and see) no reason for a destructor to ever 
> call a finalizer.

An example:

class File
{
    int fd;
    ubyte[] buffer;

    // avoiding bikeshed issues by using clear names
    destructor() { finalizer(); delete buffer; }
    finalizer() { close(fd); }
}

No reason to repeat the finalizer code in the destructor.

-Steve


More information about the Digitalmars-d mailing list