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