Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread kinke via Digitalmars-d-learn

On Monday, 4 May 2020 at 11:50:49 UTC, Steven Schveighoffer wrote:
I'm not sure if Ali is referring to this, but the usage of 
scope to allocate on the stack was at one time disfavored by 
the maintainers. This is why std.typecons.scoped was added (to 
hopefully remove that feature).


Though, if dip1000 ever becomes the default, allocating on the 
stack could be a valid optimization.


It's not an optimization, it's the status quo for years, although 
apparently not properly spec'd. And unlike the `scoped` library 
solution, `scope` is lightweight and works with -betterC too.


Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, May 04, 2020 at 09:33:27AM -0700, Ali Çehreli via Digitalmars-d-learn 
wrote:
[...]
> Now it's news to me that 'new' does not allocate on the heap when
> 'scope' is used. I'm not sure I'm comfortable with it but that's true.
> Is this unique?  Otherwise, 'new' always allocates on the heap, no?

IIRC this is by design.  The idea is that if an object is 'scope', then
it will not escape the current scope and therefore it's safe to allocate
it on the stack instead of the heap.  IIRC historically this was a
semi-hack to allow people to specify that the object should be allocated
on the stack instead of the heap, back when the semantics of 'scope'
wasn't clearly defined yet.


T

-- 
Knowledge is that area of ignorance that we arrange and classify. -- Ambrose 
Bierce


Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/4/20 12:33 PM, Ali Çehreli wrote:
Now it's news to me that 'new' does not allocate on the heap when 
'scope' is used. I'm not sure I'm comfortable with it but that's true. 
Is this unique? Otherwise, 'new' always allocates on the heap, no?


This feature was in D1 AFAIK.

So it's really old news ;)

-Steve


Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread Ali Çehreli via Digitalmars-d-learn

On 5/4/20 2:47 AM, Olivier Pisano wrote:

On Monday, 4 May 2020 at 09:20:06 UTC, Ali Çehreli wrote:
On 4/30/20 10:04 AM, Ben Jones wrote:> On Thursday, 30 April 2020 at 
16:55:36 UTC, Robert M. Münch wrote:


> I think you want to use scope rather than auto which will put
the class
> on the stack and call its destructor:
> https://dlang.org/spec/attribute.html#scope

That is correct about calling the destructor but the object would 
still be allocated with 'new', hence be on the heap. There is also 
library feature 'scoped', which places the object on the stack:


  https://dlang.org/phobos/std_typecons.html#scoped

Ali


https://godbolt.org/z/SEVsp5

My ASM skills are pretty limited, but it seems to me that the call to 
_d_allocclass is omitted when using scope. At least with LDC and GDC.


Am I missing something ?


I stand corrected.

'scope's running the destructor was news to me, so I tested with a 
writeln example where the messages changed order depending on whether 
'scope' was replaced with 'auto' or not:


import std.stdio;

class C {
  ~this() {
writeln("~this");
  }
}

void foo() {
  scope c = new C();  // <-- here
}

void main() {
  foo();
  writeln("foo returned");
}

Now it's news to me that 'new' does not allocate on the heap when 
'scope' is used. I'm not sure I'm comfortable with it but that's true. 
Is this unique? Otherwise, 'new' always allocates on the heap, no?


I added the following three lines to the end of foo() too see (without 
needing to look at assembly) that the 'scope' and 'auto' class objects 
are allocated on different memory regions (by taking object addresses as 
proof :) ):


  writeln(cast(void*)c);
  auto c2 = new C();
  writeln(cast(void*)c2);

Ali



Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/4/20 5:47 AM, Olivier Pisano wrote:

On Monday, 4 May 2020 at 09:20:06 UTC, Ali Çehreli wrote:
On 4/30/20 10:04 AM, Ben Jones wrote:> On Thursday, 30 April 2020 at 
16:55:36 UTC, Robert M. Münch wrote:


> I think you want to use scope rather than auto which will put
the class
> on the stack and call its destructor:
> https://dlang.org/spec/attribute.html#scope

That is correct about calling the destructor but the object would 
still be allocated with 'new', hence be on the heap. There is also 
library feature 'scoped', which places the object on the stack:


  https://dlang.org/phobos/std_typecons.html#scoped



https://godbolt.org/z/SEVsp5

My ASM skills are pretty limited, but it seems to me that the call to 
_d_allocclass is omitted when using scope. At least with LDC and GDC.


Am I missing something ?


I'm not sure if Ali is referring to this, but the usage of scope to 
allocate on the stack was at one time disfavored by the maintainers. 
This is why std.typecons.scoped was added (to hopefully remove that 
feature).


Though, if dip1000 ever becomes the default, allocating on the stack 
could be a valid optimization.


-Steve


Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread Olivier Pisano via Digitalmars-d-learn

On Monday, 4 May 2020 at 09:20:06 UTC, Ali Çehreli wrote:
On 4/30/20 10:04 AM, Ben Jones wrote:> On Thursday, 30 April 
2020 at 16:55:36 UTC, Robert M. Münch wrote:


> I think you want to use scope rather than auto which will put
the class
> on the stack and call its destructor:
> https://dlang.org/spec/attribute.html#scope

That is correct about calling the destructor but the object 
would still be allocated with 'new', hence be on the heap. 
There is also library feature 'scoped', which places the object 
on the stack:


  https://dlang.org/phobos/std_typecons.html#scoped

Ali


https://godbolt.org/z/SEVsp5

My ASM skills are pretty limited, but it seems to me that the 
call to _d_allocclass is omitted when using scope. At least with 
LDC and GDC.


Am I missing something ?


Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread Ali Çehreli via Digitalmars-d-learn
On 4/30/20 10:04 AM, Ben Jones wrote:> On Thursday, 30 April 2020 at 
16:55:36 UTC, Robert M. Münch wrote:


> I think you want to use scope rather than auto which will put the class
> on the stack and call its destructor:
> https://dlang.org/spec/attribute.html#scope

That is correct about calling the destructor but the object would still 
be allocated with 'new', hence be on the heap. There is also library 
feature 'scoped', which places the object on the stack:


  https://dlang.org/phobos/std_typecons.html#scoped

Ali




Re: Idomatic way to guarantee to run destructor?

2020-05-03 Thread Robert M. Münch via Digitalmars-d-learn

On 2020-05-02 20:43:16 +, Steven Schveighoffer said:

destroy sets all the values to the .init value. And it nulls the vtable 
pointer.


Ok, that makes sense. Thanks for all the deep internal details. There 
is always a lot to learn.


--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



Re: Idomatic way to guarantee to run destructor?

2020-05-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/2/20 3:08 PM, Robert M. Münch wrote:

On 2020-05-02 18:18:44 +, Steven Schveighoffer said:


On 5/2/20 4:44 AM, Robert M. Münch wrote:

How would that help, because the class instance is now unusable 
anyway. So I have it around like a zombie and others might think: 
"Hey you look normal, let's get in contact" and then you are doomed...


The difference is that if you use it, you get an error and a crash. If 
you clean up the memory, that memory could be reallocated to something 
else with a completely different type, and now you have memory 
corruption.


I didn't thought about the "memory is re-used" case here...

And how is the instance made unusable so that a crash happens (which I 
prefer too!)? Does .destroy zero the memory? Just curious how the crash 
situation is detected.




destroy sets all the values to the .init value. And it nulls the vtable 
pointer. So any virtual calls will crash with a segfault. non-virtual 
calls won't crash immediately, but generally there are few class calls 
that have all final calls.


And even if they do go through, the .init value should be harmless in 
terms of memory safety.


For reference, destroy calls this function on class instances (Same as 
GC cleanup) where p is really the class reference:


https://github.com/dlang/druntime/blob/999367be8fa5d13a718d951d67c3d580ca13aef1/src/rt/lifetime.d#L1414

You can see in the finally clause, the vptr is set to null.

-Steve


Re: Idomatic way to guarantee to run destructor?

2020-05-02 Thread Robert M. Münch via Digitalmars-d-learn

On 2020-05-02 18:18:44 +, Steven Schveighoffer said:


On 5/2/20 4:44 AM, Robert M. Münch wrote:

How would that help, because the class instance is now unusable anyway. 
So I have it around like a zombie and others might think: "Hey you look 
normal, let's get in contact" and then you are doomed...


The difference is that if you use it, you get an error and a crash. If 
you clean up the memory, that memory could be reallocated to something 
else with a completely different type, and now you have memory 
corruption.


I didn't thought about the "memory is re-used" case here...

And how is the instance made unusable so that a crash happens (which I 
prefer too!)? Does .destroy zero the memory? Just curious how the crash 
situation is detected.


--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



Re: Idomatic way to guarantee to run destructor?

2020-05-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/2/20 4:44 AM, Robert M. Münch wrote:

On 2020-04-30 17:45:24 +, Steven Schveighoffer said:

You can use scope instead of auto, and it will then allocate the class 
on the stack, and destroy it as Ben Jones said. There is danger there, 
however, as it's very easy to store a class reference elsewhere, and 
then you have a dangling pointer.



Ok. Can't this be combined with some "don't let the refrence escape my 
function" feature of D?


I don't know. perhaps dip1000 helps here.




A safer thing to do is:


auto X = new MyClass();

scope(exit) destroy(X);


This runs the destructor and makes the class instance unusable, but does 
not free the memory (so any remaining references, if used, will not 
corrupt memory).



How would that help, because the class instance is now unusable anyway. 
So I have it around like a zombie and others might think: "Hey you look 
normal, let's get in contact" and then you are doomed...


The difference is that if you use it, you get an error and a crash. If 
you clean up the memory, that memory could be reallocated to something 
else with a completely different type, and now you have memory corruption.


-Steve


Re: Idomatic way to guarantee to run destructor?

2020-05-02 Thread Robert M. Münch via Digitalmars-d-learn

On 2020-04-30 17:45:24 +, Steven Schveighoffer said:

No, auto is declaring that there's about to be a variable here. In 
actuality, auto does nothing in the first case, it just means local 
variable. But without the type name, the type is inferred (i.e. your 
second example). This does not do any automatic destruction of your 
class, it's still left to the GC.


Ok, that was my understand too. As said, I found some older posts and 
was a bit confused...


You can use scope instead of auto, and it will then allocate the class 
on the stack, and destroy it as Ben Jones said. There is danger there, 
however, as it's very easy to store a class reference elsewhere, and 
then you have a dangling pointer.


Ok. Can't this be combined with some "don't let the refrence escape my 
function" feature of D?



A safer thing to do is:

auto X = new MyClass();
scope(exit) destroy(X);

This runs the destructor and makes the class instance unusable, but 
does not free the memory (so any remaining references, if used, will 
not corrupt memory).


How would that help, because the class instance is now unusable anyway. 
So I have it around like a zombie and others might think: "Hey you look 
normal, let's get in contact" and then you are doomed...


If your concern is guaranteeing destructors are run, that's what I 
would pick. If in addition you want guaranteed memory cleanup, then use 
scope (and be careful).


Ok, thanks.

--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

Re: Idomatic way to guarantee to run destructor?

2020-05-02 Thread Robert M. Münch via Digitalmars-d-learn

On 2020-04-30 17:04:43 +, Ben Jones said:

I think you want to use scope rather than auto which will put the class 
on the stack and call its destructor: 
https://dlang.org/spec/attribute.html#scope


Yes, thanks.

--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



Re: Idomatic way to guarantee to run destructor?

2020-04-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/30/20 12:55 PM, Robert M. Münch wrote:
For ressource management I mostly use this pattern, to ensure the 
destructor is run:


void myfunc(){
  MyClass X = new MyClass(); scope(exit) X.destroy;
}

I somewhere read, this would work too:

void myfunc(){
  auto MyClass X = new MyClass();
}

What does this "auto" does here? Wouldn't

void myfunc(){
  auto X = new MyClass();
}

be sufficient? And would this construct guarantee that the destructor is 
run? And if, why does "auto" has this effect, while just using "new" 
doesn't guarantee to run the destructor?


No, auto is declaring that there's about to be a variable here. In 
actuality, auto does nothing in the first case, it just means local 
variable. But without the type name, the type is inferred (i.e. your 
second example). This does not do any automatic destruction of your 
class, it's still left to the GC.


You can use scope instead of auto, and it will then allocate the class 
on the stack, and destroy it as Ben Jones said. There is danger there, 
however, as it's very easy to store a class reference elsewhere, and 
then you have a dangling pointer.


A safer thing to do is:

auto X = new MyClass();
scope(exit) destroy(X);

This runs the destructor and makes the class instance unusable, but does 
not free the memory (so any remaining references, if used, will not 
corrupt memory).


If your concern is guaranteeing destructors are run, that's what I would 
pick. If in addition you want guaranteed memory cleanup, then use scope 
(and be careful).


-Steve


Re: Idomatic way to guarantee to run destructor?

2020-04-30 Thread Ben Jones via Digitalmars-d-learn

On Thursday, 30 April 2020 at 16:55:36 UTC, Robert M. Münch wrote:
For ressource management I mostly use this pattern, to ensure 
the destructor is run:


void myfunc(){
 MyClass X = new MyClass(); scope(exit) X.destroy;
}

I somewhere read, this would work too:

void myfunc(){
 auto MyClass X = new MyClass();
}

What does this "auto" does here? Wouldn't

void myfunc(){
 auto X = new MyClass();
}

be sufficient? And would this construct guarantee that the 
destructor is run? And if, why does "auto" has this effect, 
while just using "new" doesn't guarantee to run the destructor?



I think you want to use scope rather than auto which will put the 
class on the stack and call its destructor: 
https://dlang.org/spec/attribute.html#scope