Should destructors be able to tell who called them?

Steven Schveighoffer schveiguy at yahoo.com
Tue Aug 10 12:00:19 PDT 2010


On Tue, 10 Aug 2010 14:56:54 -0400, Mafi <mafi at example.org> wrote:

> Am 10.08.2010 20:25, schrieb Steven Schveighoffer:
>> One of the common problems of destructors is that they cannot assume any
>> of their GC-allocated resources are valid when inside the destrutor.
>>
>> The spec says:
>>
>> The garbage collector is not guaranteed to run the destructor for all
>> unreferenced objects. Furthermore, the order in which the garbage
>> collector calls destructors for unreference objects is not specified.
>> This means that when the garbage collector calls a destructor for an
>> object of a class that has members that are references to garbage
>> collected objects, those references may no longer be valid. This means
>> that destructors cannot reference sub objects. This rule does not apply
>> to auto objects or objects deleted with the DeleteExpression, as the
>> destructor is not being run by the garbage collector, meaning all
>> references are valid.
>>
>> Let's analyze that last sentence (BTW, I think where it says auto, it
>> should say scope). "This does not apply to objects deleted with the
>> DeleteExpression..." Well, how the hell do you know while in the
>> destructor whether you were called via delete/clear or from the GC? You
>> don't. So the destructor *must* be written as if you are called from the
>> GC, because the GC may be calling it, it is up to the user to determine
>> whether your class will be destroyed via delete/clear or the GC. So you
>> must assume worst case. Unless you declare your class as scope, which I
>> don't even know if anyone does that anymore (I think it's scheduled for
>> deprecation anyways).
>>
>> But, what if the destructor was given an idea of whether its resources
>> are valid or not? Then you could do something different based on that
>> input.
>>
>> For example, an object that wants to open a file can do so, and in the
>> destructor, use the determination of validity to decide whether to close
>> the file or not.
>>
>> This can be implemented by an optional parameter to the destructor
>> that's always passed, but it's not necessary to use it. i.e. you could
>> declare your destructor like this:
>>
>> ~this(bool deterministic)
>> {
>> if(deterministic) file.close();
>> }
>>
>> or like this:
>>
>> ~this()
>> {
>> }
>>
>> Scope classes (if allowed to exist) or calls to clear will set
>> deterministic to true. The GC will set it to false.
>>
>> This would make destructors a lot more useful. Thoughts?
>>
>> -Steve
>
> Interestingly I had exactly the same idea a few hours ago as I red the  
> discussions about clear. I just forgot about it without posting.
>
> I think it's a good idea. The ignorant destructor (ie w/o parameter)  
> defenition should be inetrnally rewritten to accept an ignored bool  
> parameter. This would make the following thing a doubled and therfore  
> incorrect definition.
>
> class X {
>    ~this(){}
>    ~this(bool det){}
> }
>
> If the compiler then adds an overload for 'X.__dtor()' which simply  
> calls 'X.__dtor(false)' [1], we should be totally compatible with  
> existing code.

pushing an ignored argument on the stack doesn't matter.  Basically,  
__dtor would always have a bool argument, and if the definition of the  
class had ~this(), it doesn't matter.

It's the reason you can have main either accept a string array or nothing.

-Steve


More information about the Digitalmars-d mailing list