View mode: basic / threaded / horizontal-split · Log in · Help
September 04, 2011
clear bug?
Using dmd 2.054 on osx:

Calling a instance method after using clear() on an instance is giving
me a bus error.  The instance fields look like they are cleared ok, just
can't safely call a method.  I think this used to work after the object
was cleared, and was the reason for clear() over the deprecated delete.

Dan
=-=-=
Sample:
import std.stdio;

class A
{
  string name = "none";
  void print() {writeln(name);}
}

void main()
{
  A a = new A;
  a.print();                           // none

  a.name = "xyzzy";
  a.print();                           // xyzzy

  clear(a);
  writeln(a.name);                     // a is reinit to "none" as expected
  a.print();                           // bus error?
}

Output:
$ dmd clearbug.d
$ ./clearbug
none
xyzzy
none
Bus error
September 05, 2011
Re: clear bug?
On Sun, 04 Sep 2011 12:30:58 -0700, Dan Olson wrote:

> Using dmd 2.054 on osx:
> 
> Calling a instance method after using clear() on an instance is giving
> me a bus error.

"Segmentation fault" on my Ubuntu.

> The instance fields look like they are cleared ok, just
> can't safely call a method.

I think that's by design. A cleared object is in an unusable state. In 
fact, I think the implementation actually nulls its vtable pointer.

> I think this used to work after the object
> was cleared,

Correct. In the earlier design the object would be in a default 
initialized state, which would call the destructor twice. Not anymore. I 
think this has changed since the TDPL has been written. (I've just e-
mailed Andrei about the broken link to the "shouldwork" section on http://
erdani.com/tdpl/errata/ )

> and was the reason for clear() over the deprecated delete.

delete used to destroy the object give the memory back. clear just calls 
the destructor. The idea is that the programmer shouldn't have much say 
on a new'ed object's memory.

I think the thought was, if the programmers really cared they could 
allocate the memory from a private memory pool.

> 
> Dan

Ali

> =-=-=
> Sample:
> import std.stdio;
> 
> class A
> {
>    string name = "none";
>    void print() {writeln(name);}
> }
> 
> void main()
> {
>    A a = new A;
>    a.print();                           // none
> 
>    a.name = "xyzzy";
>    a.print();                           // xyzzy
> 
>    clear(a);
>    writeln(a.name);                     // a is reinit to "none" as
>    expected a.print();                           // bus error?
> }
> 
> Output:
> $ dmd clearbug.d
> $ ./clearbug
> none
> xyzzy
> none
> Bus error
September 06, 2011
Re: clear bug?
clear() nulls out the vtable.
September 06, 2011
Re: clear bug?
On Sunday, September 04, 2011 12:30:58 Dan Olson wrote:
> Using dmd 2.054 on osx:
> 
> Calling a instance method after using clear() on an instance is giving
> me a bus error.  The instance fields look like they are cleared ok, just
> can't safely call a method.  I think this used to work after the object
> was cleared, and was the reason for clear() over the deprecated delete.

Once an object has been cleared, it's invalid. Don't use it. Why would you 
ever try and use an object that had been cleared or deleted? The memory for it 
has been released!

The reason that delete was deprecated was because it was deemed a bad idea in 
a garbage collected language. It has _nothing_ to do with calling functions on 
an object after it has been cleared or deleted.

- Jonathan M Davis
September 06, 2011
Re: clear bug?
On 9/6/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> Why would you
> ever try and use an object that had been cleared?

TDPL, that's why. Things might have changed but how would someone new
to D know that?
September 06, 2011
Re: clear bug?
On Tuesday, September 06, 2011 02:12:11 Andrej Mitrovic wrote:
> On 9/6/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> > Why would you
> > ever try and use an object that had been cleared?
> 
> TDPL, that's why. Things might have changed but how would someone new
> to D know that?

I really don't pay much attention to clear, since I rarely use it, and I don't 
know why you'd ever actually want to try and use an object that you cleared. I 
do remember discussions about making it clear out the vtable, since you _want_ 
it to blow up after it's been cleared rather than have an invalid object work 
on some level. Rereading the relevant section in TDPL though, it does look 
like it describes a different situation than seems to have been ultimately 
settled on. So, I guess that I don't know exactly what the situation currently 
is or what it's supposed to be. But I wouldn't have expected clear to result 
in a valid object. But clearing out the vtable at least makes it blow up 
nicely instead of doing who knows what with memory when you try and call 
functions on an invalid object. So, if the ultimate goal is just to make it 
memory safe, then both clearing out the vtable and the situation that TDPL 
describes do the trick, though deleting the vtable actually helps tell you 
that you've used an object when you shouldn't, whereas TDPL's description 
results in using the object succeeding, which probably isn't a good thing.

- Jonathan M Davis
September 06, 2011
Re: clear bug?
Jonathan M Davis <jmdavisProg@gmx.com> writes:

> On Tuesday, September 06, 2011 02:12:11 Andrej Mitrovic wrote:
>> On 9/6/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>> > Why would you
>> > ever try and use an object that had been cleared?
>> 
>> TDPL, that's why. Things might have changed but how would someone new
>> to D know that?
>
> I really don't pay much attention to clear, since I rarely use it, and I don't 
> know why you'd ever actually want to try and use an object that you cleared. I 
> do remember discussions about making it clear out the vtable, since you _want_ 
> it to blow up after it's been cleared rather than have an invalid object work 
> on some level. Rereading the relevant section in TDPL though, it does look 
> like it describes a different situation than seems to have been ultimately 
> settled on. So, I guess that I don't know exactly what the situation currently 
> is or what it's supposed to be. But I wouldn't have expected clear to result 
> in a valid object. But clearing out the vtable at least makes it blow up 
> nicely instead of doing who knows what with memory when you try and call 
> functions on an invalid object. So, if the ultimate goal is just to make it 
> memory safe, then both clearing out the vtable and the situation that TDPL 
> describes do the trick, though deleting the vtable actually helps tell you 
> that you've used an object when you shouldn't, whereas TDPL's description 
> results in using the object succeeding, which probably isn't a good thing.
>
> - Jonathan M Davis

Thanks for the clearification.

It was based on TDPL 6.3.5 that I thought the idea of clear() was to
clean up but leave the thing in an initialized state.  And because
clear() on dynamic arrays and other types seems to be be intended to
leave you with a valid and initialized object.  Or is that not true?

Dan
September 06, 2011
Re: clear bug?
On Monday, September 05, 2011 19:05:56 Dan Olson wrote:
> Jonathan M Davis <jmdavisProg@gmx.com> writes:
> > On Tuesday, September 06, 2011 02:12:11 Andrej Mitrovic wrote:
> >> On 9/6/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> >> > Why would you
> >> > ever try and use an object that had been cleared?
> >> 
> >> TDPL, that's why. Things might have changed but how would someone new
> >> to D know that?
> > 
> > I really don't pay much attention to clear, since I rarely use it, and I
> > don't know why you'd ever actually want to try and use an object that
> > you cleared. I do remember discussions about making it clear out the
> > vtable, since you _want_ it to blow up after it's been cleared rather
> > than have an invalid object work on some level. Rereading the relevant
> > section in TDPL though, it does look like it describes a different
> > situation than seems to have been ultimately settled on. So, I guess
> > that I don't know exactly what the situation currently is or what it's
> > supposed to be. But I wouldn't have expected clear to result in a valid
> > object. But clearing out the vtable at least makes it blow up nicely
> > instead of doing who knows what with memory when you try and call
> > functions on an invalid object. So, if the ultimate goal is just to
> > make it memory safe, then both clearing out the vtable and the
> > situation that TDPL describes do the trick, though deleting the vtable
> > actually helps tell you that you've used an object when you shouldn't,
> > whereas TDPL's description results in using the object succeeding,
> > which probably isn't a good thing.
> > 
> > - Jonathan M Davis
> 
> Thanks for the clearification.
> 
> It was based on TDPL 6.3.5 that I thought the idea of clear() was to
> clean up but leave the thing in an initialized state.  And because
> clear() on dynamic arrays and other types seems to be be intended to
> leave you with a valid and initialized object.  Or is that not true?

I don't really know what the current state of clear is. I know that there were 
issues which caused people to want clear to zero-out the vtable on objects, 
and I believe that that's what it currently does. One of the reasons for clear 
appears to be to make it memory-safe - and both putting the object in a 
default state and zeroing out the vtable will do that. It's just that in the 
one case, you can use it (though you probably shouldn't be and its state isn't 
very interesting), while in the other, it will blow up if you use it.

Dynamic arrays don't have vtables, so there's no way that calling clear on 
them would zero-out their vtable. I was unaware that you even could call clear 
on them (I really don't use clear much). I would have guessed that doing so 
would just call clear on each of its elements and then set the array's length 
to 0 (and probably its ptr to null), but I don't know. I really don't use 
clear (it's not generally supposed to be necessary), so I don't know exactly 
what it's state is or how it differs (if at all) from how it's supposed to 
work.

- Jonathan M Davis
September 06, 2011
Re: clear bug?
On Mon, 05 Sep 2011 22:05:56 -0400, Dan Olson <zans.is.for.cans@yahoo.com>  
wrote:

> Jonathan M Davis <jmdavisProg@gmx.com> writes:
>
>> On Tuesday, September 06, 2011 02:12:11 Andrej Mitrovic wrote:
>>> On 9/6/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>>> > Why would you
>>> > ever try and use an object that had been cleared?
>>>
>>> TDPL, that's why. Things might have changed but how would someone new
>>> to D know that?
>>
>> I really don't pay much attention to clear, since I rarely use it, and  
>> I don't
>> know why you'd ever actually want to try and use an object that you  
>> cleared. I
>> do remember discussions about making it clear out the vtable, since you  
>> _want_
>> it to blow up after it's been cleared rather than have an invalid  
>> object work
>> on some level. Rereading the relevant section in TDPL though, it does  
>> look
>> like it describes a different situation than seems to have been  
>> ultimately
>> settled on. So, I guess that I don't know exactly what the situation  
>> currently
>> is or what it's supposed to be. But I wouldn't have expected clear to  
>> result
>> in a valid object. But clearing out the vtable at least makes it blow up
>> nicely instead of doing who knows what with memory when you try and call
>> functions on an invalid object. So, if the ultimate goal is just to  
>> make it
>> memory safe, then both clearing out the vtable and the situation that  
>> TDPL
>> describes do the trick, though deleting the vtable actually helps tell  
>> you
>> that you've used an object when you shouldn't, whereas TDPL's  
>> description
>> results in using the object succeeding, which probably isn't a good  
>> thing.
>>
>> - Jonathan M Davis
>
> Thanks for the clearification.
>
> It was based on TDPL 6.3.5 that I thought the idea of clear() was to
> clean up but leave the thing in an initialized state.  And because
> clear() on dynamic arrays and other types seems to be be intended to
> leave you with a valid and initialized object.  Or is that not true?

There is a large issue with leaving a class in a "valid state".  A class's  
valid state only occurs after a constructor is called.  The same is not  
true for structs.

So we have problems:

1. what if the class has no default constructor?  What to use as  
parameters?
2. if it does have a default constructor, what if that default constructor  
is costly, or allocates more resources?  Didn't we just designate it for  
destruction?

The point of clear is to call the *destructor*, not the constructor, and  
not deallocate the memory.  We could have left the object data in its init  
state (i.e. before any ctor is called), but that would leave the false  
impression that it's valid.  By clearing out the vtable, we guarantee it's  
not valid and that any usage will create a huge noticeable error.

Basically, if you clear an object, or an array, or anything, you are  
saying "I no longer need this, GC, collect this when you can" you  
shouldn't use it again unless you reinitialize it.  All dtors are called,  
and it's invariant may be invalid.  The only thing that's left is a  
placeholder to ensure you cannot corrupt anything else.

However, you can reassign it to a newly initialized struct or object, and  
you can continue to use it after that.

-Steve
Top | Discussion index | About this forum | D home