TDPL: Manual invocation of destructor

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Aug 9 14:17:13 PDT 2010


Steven Schveighoffer wrote:
> On Mon, 09 Aug 2010 16:31:39 -0400, Andrei Alexandrescu 
> <SeeWebsiteForEmail at erdani.org> wrote:
> 
>> Steven Schveighoffer wrote:
>>> On Mon, 09 Aug 2010 15:46:27 -0400, Andrei Alexandrescu 
>>> <SeeWebsiteForEmail at erdani.org> wrote:
>>>
>>>> Lutger wrote:
>>>>> Steven Schveighoffer wrote:
>>>>>
>>>>>> On Mon, 09 Aug 2010 08:28:38 -0400, Andrej Mitrovic
>>>>>> <andrej.mitrovich at gmail.com> wrote:
>>>>>>
>>>>>>> It's rather perplexing, isn't it? It states in TDPL:
>>>>>>>
>>>>>>> "After you invoke clear, the object is still alive and well, but its
>>>>>>> destructor has been called and the object is now carrying its
>>>>>>> default-constructed stated. During the next garbage collection, the
>>>>>>> destructor is called again, because the garbage collector has no 
>>>>>>> idea in
>>>>>>> what state you have left the object."
>>>>>> This seems totally wrong, what if an object has no default 
>>>>>> constructor?
>>>>>> The spec used to say (maybe it still does) that a destructor is 
>>>>>> guaranteed
>>>>>> to only ever be called once.
>>>>>  The spec still does, it is not updated since it describes delete, 
>>>>> not clear.  If you omit the default constructor, no constructor 
>>>>> will be called. Also not for the base classes even if they have a 
>>>>> default constructor. This looks like a bug.
>>>>
>>>> Yes, not calling the constructors of base classes is an 
>>>> implementation bug. If a class does not define any constructor at 
>>>> all, it has a de facto default constructor. If a class does define 
>>>> some constructor but not a parameterless one, it is a bug in the 
>>>> implementation if clear() compiles.
>>>  How can this be decided at compile time?
>>>  basic counter-example:
>>>  class C
>>> {
>>>    this(int x) {}
>>> }
>>>  // how do you statically disable this?
>>> void foo(Object o)
>>> {
>>>   clear(o);
>>> }
>>>  void foo(C c)
>>> {
>>>    auto c = new C(1);
>>>    foo(c);
>>> }
>>
>> Sorry, I got things mixed.
>>
>>> I always thought clear would simply overwrite the object with it's 
>>> default data as defined in the TypeInfo (i.e. before a constructor is 
>>> normally called).  Calling the constructor is absolutely wrong.  We 
>>> don't want to reset the object, we want to free it's resources.  
>>> Re-constructing it may reallocate resources *THAT WE JUST ASKED TO BE 
>>> DESTROYED MANUALLY*.  To say clear as defined is a replacement for 
>>> delete is complete fantasy.
>>
>> Well this is my view as well and the original intent of clear(). The 
>> problem is, if someone defined a default constructor, they presumably 
>> have a nontrivial invariant to satisfy. I'm unclear on what's the best 
>> path to take.
> 
> Who cares about invariants when an object is destructed?

The destructor itself.

> First, 
> invariants are disabled in release mode.

I was refering to invariant in-the-large, not D's invariant keyword and 
associated notion.

> I also strongly suggest the destructor only be called once.  Having a 
> destructor called more than once means your destructor has to take into 
> account that the object may be already destructed.  This would be helped 
> by the same mechanism that would make sure invariants aren't run after 
> destruction.

If some constructor has been called in between two calls to the 
destructor, there's shouldn't be any danger.


Andrei


More information about the Digitalmars-d mailing list