Re: Question about Object.destroy

2015-09-20 Thread Lambert Duijst via Digitalmars-d-learn

On Sunday, 20 September 2015 at 18:50:44 UTC, Adam D. Ruppe wrote:

On Sunday, 20 September 2015 at 18:41:18 UTC, anonymous wrote:

But that doesn't change either. I think Adam is mistaken here.


huh, I just checked the source... and you are right, it doesn't 
set classes to null itself, but does null out the vtable inside.


*ppv = null; // zero vptr even if `resetMemory` is false

druntime/src/rt/lifetime.d line 1373

So that's why it is segfaulting, the table of virtual functions 
is nulled after it is destroyed rather than the reference.


Oops, I think I replied too fast, did not read this reply of 
yours, which answers some of my questions. If the vtable is 
nulled then this will always lead to a segfault when methods of 
deleted object are called, which is good because doing so is a 
programming error anyway, but at least it does not lead to weird 
memory corruptions etc..


Re: Question about Object.destroy

2015-09-20 Thread ponce via Digitalmars-d-learn
On Sunday, 20 September 2015 at 17:43:01 UTC, Lambert Duijst 
wrote:


Is it because:

 - The GC did decide to run and cleanup memory straight after 
the call to s.destroy()
 - An object being in an invalid state means the program 
segfaults when the object is used ?

 - Another reason..


All methods are virtual by default.
My guess would be that the invalid state implies that the virtual 
table pointer is not valid anymore, hence the crash.





Re: Question about Object.destroy

2015-09-20 Thread anonymous via Digitalmars-d-learn
On Sunday 20 September 2015 20:34, Lambert Duijst wrote:

> On Sunday, 20 September 2015 at 18:21:52 UTC, Adam D. Ruppe wrote:
[...]
>> So after calling destroy(s), s is null, so it segfaults when 
>> you try to use it.
[...]
> Also when I print the address of s it gives me some hex number, 
> but not 0 (null).
> I use writeln("Address of s ", ) to print the address, not sure 
> if that is correct though.
> Before and after the explicit destroy I get the same address, 
> which is 7FFF549108D8.

 is the address of the variable. We're not interested that but in the 
reference that's stored in s. You can print that by casting to void*:

writeln(cast(void*) s);

But that doesn't change either. I think Adam is mistaken here.


Re: Question about Object.destroy

2015-09-20 Thread Lambert Duijst via Digitalmars-d-learn

On Sunday, 20 September 2015 at 18:21:52 UTC, Adam D. Ruppe wrote:
Very simple: destroy(s) (or s.destroy but i prefer destroy(s)) 
will set the reference it is passed to null because you aren't 
supposed to use it anymore.


So after calling destroy(s), s is null, so it segfaults when 
you try to use it.


Oh that surprises me a bit, because I read in the list of 
deprecated features that delete is deprecated and that the right 
thing to do is to use destroy instead.


Also when I print the address of s it gives me some hex number, 
but not 0 (null).
I use writeln("Address of s ", ) to print the address, not sure 
if that is correct though.
Before and after the explicit destroy I get the same address, 
which is 7FFF549108D8.


Btw I use dmd v2.067 on mac os 10.10.3

Thanks for the quick replies.


Re: Question about Object.destroy

2015-09-20 Thread Adam D. Ruppe via Digitalmars-d-learn
Very simple: destroy(s) (or s.destroy but i prefer destroy(s)) 
will set the reference it is passed to null because you aren't 
supposed to use it anymore.


So after calling destroy(s), s is null, so it segfaults when you 
try to use it.


Re: Question about Object.destroy

2015-09-20 Thread Adam D. Ruppe via Digitalmars-d-learn
On Sunday, 20 September 2015 at 18:34:37 UTC, Lambert Duijst 
wrote:
Oh that surprises me a bit, because I read in the list of 
deprecated features that delete is deprecated and that the 
right thing to do is to use destroy instead.


Right. One of the benefits of destroy is that it nulls the 
reference. Once you destroy it, you aren't supposed to use it 
again*. The zombie is kept around until the GC reaps it to 
protect against dangling pointers (somewhat), but you still 
aren't actually supposed to reuse it.


* If you really want to you can cheat by making a separate local 
variable to hold it before destroy it... destroy only nulls the 
variable you pass in, but I do not recommend doing this. Instead, 
you should reconstruct the object, even if implementing an object 
pool or something.


I use writeln("Address of s ", ) to print the address, not 
sure if that is correct though.


that gives you the address of the local variable, not the 
reference. For address of the reference, try `cast(void*) s`.


An Object in D is like an Object* in C++. So when you & it, you 
get a pointer to a pointer.


Re: Question about Object.destroy

2015-09-20 Thread Adam D. Ruppe via Digitalmars-d-learn

On Sunday, 20 September 2015 at 18:41:18 UTC, anonymous wrote:

But that doesn't change either. I think Adam is mistaken here.


huh, I just checked the source... and you are right, it doesn't 
set classes to null itself, but does null out the vtable inside.


*ppv = null; // zero vptr even if `resetMemory` is false

druntime/src/rt/lifetime.d line 1373

So that's why it is segfaulting, the table of virtual functions 
is nulled after it is destroyed rather than the reference.


Re: Question about Object.destroy

2015-09-20 Thread Lambert Duijst via Digitalmars-d-learn

On Sunday, 20 September 2015 at 18:39:57 UTC, Adam D. Ruppe wrote:
On Sunday, 20 September 2015 at 18:34:37 UTC, Lambert Duijst 
wrote:
Oh that surprises me a bit, because I read in the list of 
deprecated features that delete is deprecated and that the 
right thing to do is to use destroy instead.


Right. One of the benefits of destroy is that it nulls the 
reference. Once you destroy it, you aren't supposed to use it 
again*. The zombie is kept around until the GC reaps it to 
protect against dangling pointers (somewhat), but you still 
aren't actually supposed to reuse it.


* If you really want to you can cheat by making a separate 
local variable to hold it before destroy it... destroy only 
nulls the variable you pass in, but I do not recommend doing 
this. Instead, you should reconstruct the object, even if 
implementing an object pool or something.


I use writeln("Address of s ", ) to print the address, not 
sure if that is correct though.


that gives you the address of the local variable, not the 
reference. For address of the reference, try `cast(void*) s`.


An Object in D is like an Object* in C++. So when you & it, you 
get a pointer to a pointer.


Ah, that clarifies a lot ! Thanks. Also does destroy set all 
references to that object to null in this case there was only 1, 
but in a real program there can of course be many references to 
an object.


I wasn't interested in reusing an object after it was deleted, 
but more in the behaviour of a program if you do use it after a 
deletion. Just want to know if D protects against dangling 
pointers or is this just something you should never do.


If we are not supposed to use Object.destroy anymore then how can 
we still free non-memory resources that are held by classes 
(which are typically cg'ed) in a deterministic way ?




Re: Question about Object.destroy

2015-09-20 Thread Lambert Duijst via Digitalmars-d-learn

Thank you, this clarified a lot.


Question about Object.destroy

2015-09-20 Thread Lambert Duijst via Digitalmars-d-learn

Hi all,

I have a question about the following piece of code that I wrote 
to experiment with explicit deletion of objects. I am interested 
in this because, even though D has a garbage collection, 
sometimes an object holds a non-memory resource, such as a file 
handle. In these cases explicit calls to a destructor are needed 
if you want deterministic release of resources.


The code I wrote is this :

import std.stdio;

class MyClass
{
  this(int a) {this.a = a;}
  ~this()
  {
writeln("Destructor call");
  }

  void doSomething()
  {
writeln("A is ", this.a);
  }
  int a;
};


void main(string args[])
{
  MyClass s = new MyClass(42);
  s.doSomething();
  s.destroy();
  s.doSomething();
}

The output of this program is:

A is 42
Destructor call

And then it segfaults.

This is obviously because of that last call to doSomething
Now the description of Object.destroy mentions that no GC memory 
is freed by Object.destroy. It does, however, put the object in 
an invalid state, but what does that mean and why does my program 
segfault.


Is it because:

 - The GC did decide to run and cleanup memory straight after the 
call to s.destroy()
 - An object being in an invalid state means the program 
segfaults when the object is used ?

 - Another reason..

And more importantly, can this way of programming with explicit 
destroy calls lead to memory corruption due to dangling pointers 
? or will D always let your program segfault whenever a deleted 
object is accessed ?


Please enlighten me, I am just a newbie :-)




Re: Question about Object.destroy

2015-09-20 Thread Adam D. Ruppe via Digitalmars-d-learn
On Sunday, 20 September 2015 at 18:52:17 UTC, Lambert Duijst 
wrote:
Just want to know if D protects against dangling pointers or is 
this just something you should never do.


The answer is both: it tries to protect you but you still 
shouldn't do it.


If we are not supposed to use Object.destroy anymore then how 
can we still free non-memory resources that are held by classes 
(which are typically cg'ed) in a deterministic way ?


The function btw is actually destroy(Object). It works as 
Object.destroy because of the uniform function call syntax 
feature which will rewrite it. But I recommend doing 
destroy(Object) because then you get consistent results, even if 
an interface has its own destroy method.


But you can use it, destroy is cool. delete was teh problem 
because it doesn't provide even the minimal protection the 
destroy function has.


(You can also malloc/free or stack allocate if you really want to 
take matters into your own hands but then the language basically 
doesn't help you at all in the dangling pointer problem.)