clear() causes crash?

Steven Schveighoffer schveiguy at yahoo.com
Mon May 13 07:30:30 PDT 2013


On Fri, 10 May 2013 22:37:43 -0400, Denis Shelomovskij  
<verylonglogin.reg at gmail.com> wrote:

> 30.04.2013 1:04, "Luís Marques" <luismarques at gmail.com>" пишет:
>> This crashes in the last line of main:
>>
>>      class A
>>      {
>>          void foo() {}
>>      }
>>
>>      void main()
>>      {
>>          A a = new A();
>>          a.foo();
>>          clear(a);
>>          assert(a !is null);
>>          a.foo();  // crashes
>>      }
>>
>> As far as I understand from TDPL book, this should not crash, but it
>> does (DMD64 v2.062, OS X). Am I misunderstanding clear()?

TDPL states that the object is required to be in a valid state.  This  
necessarily requires calling a constructor on an object, as an object has  
no valid initial state.

There are major issues with that requirement, though:

1. How to call a ctor for an object that does not have a default ctor?  In  
other words, it requires valid ctor parameters, which the runtime cannot  
possibly know.
2. What if the ctor adds the class instance to a global or some other  
rooted memory item?  That is, what if the entire point of clearing it is  
so it was not pointed to as being allocated, so the GC would remove it.

So the decision was made (correctly) to simply make any object that was  
destroyed be an invalid object.  structs will return to their .init value  
(which may also be invalid depending on the struct).

>> BTW, why not make clear also change 'a' to null?

That could also be done, but it is superficial:

auto b = a;
destroy(a);
b.foo();

The only valid thing to do with a after destroying it is to stop using it,  
and all other references to that instance.

>
> Ideally is should throw with pretty message but it isn't implemented.  
> See Issue 8139 - Make objects really disposable by addition of "Object  
> finalized" assertion [1].
>
> IMO, also `destroy` (renamed `clear`) looks like the worst mistake in D  
> runtime and I'd recommend to not use it (or better recompile  
> druntime+phobos without it for your own use). See Issue 9139 - `destroy`  
> is dangerous and inconsistent [2]. Use  
> `unstd.lifetime.finalizeClassInstance` [3] and friends for user-defined  
> lifetime implementation to avoid serious problems.
>
> [1] http://d.puremagic.com/issues/show_bug.cgi?id=8139
> [2] http://d.puremagic.com/issues/show_bug.cgi?id=9139
> [3]  
> http://denis-sh.github.io/phobos-additions/unstd.lifetime.html#finalizeClassInstance
>

I'm curious why you think it is bad.  All you have said here is that it is  
bad, not why.  Even bug 9139 says "look at how horrible this is" but  
doesn't explain why.

The point of destroy is to call destructors without deallocation.  The  
original charter said to leave the object in a default state, but that  
requires re-calling the constructor.

In the latest iteration, it simply calls the finalize function in the  
runtime.  you are not supposed to use it after calling destroy.

Not being defensive, I simply don't understand the objection.

-Steve


More information about the Digitalmars-d mailing list