September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | You're right. This is my next try: http://dpaste.dzfl.pl/02b32d33 Do you have anything else to say? :) |
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Thursday, 20 September 2012 at 08:10:36 UTC, Namespace wrote: > You're right. > This is my next try: http://dpaste.dzfl.pl/02b32d33 > Do you have anything else to say? :) I think it looks good, but I'm unsure about "move", or allowing pass by value: Classes can't be memcopied the way structs can: Class may have default constructors, or copy constructors, which would be totally ignored by a memcopy. For example, if your class had a "RefCounted" member, its postblit would never be called, and it would then be "over destroyed": -------- class A { RefCounted!int rf; this() { rf.RefCounted.ensureInitialized(); rf = 5; } } void main() { A a = new A(); OnStack!A osa = OnStack!A.move(a); } -------- core.exception.InvalidMemoryOperationError -------- Here, osa makes a binary copy of the RefCounted, so the count stays at 1. Then, when osa is destroyed, it deletes the RefCounted's store. However, when a is destroyed, it still has a pointer to the (deleted) store, creating the Error... I think "move" has to go, because classes are just not moveable. pass by value can stay, if and only if, T gives a copy constructor. Or NO constructors (in which case a memcopy should be the same as a default copy). |
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | Am Thu, 20 Sep 2012 10:11:37 +0200
schrieb "Namespace" <rswhite4@googlemail.com>:
> You're right.
> This is my next try: http://dpaste.dzfl.pl/02b32d33
> Do you have anything else to say? :)
I think it shouldn't be possible to copy an OnStack struct. The destructor is run for every copy, but the constructor was run only once. So if a class keeps external references (e.g. file handles) and closes those handles in the destructor, making a copy would result in the destructor running twice and therefore closing the same handle twice.
I think the usage of a OnStack struct must be quite limited to be safe:
{
auto a = OnStack!(A)(); //allocate in scope
a.doSomething(); //Calling members is fine
//a.get and a must not escape this scope (I guess we can't guarantee
//that without compiler help?)
//passing a.get to a function is valid, as long as the function
//doesn't keep a reference (the function parameter must be marked
//with scope)
someMethod(a.get);
//As a shouldn't be copied, an OnStack can't be passed to another
//function.
//no copies for OnStack allowed
//destroy at end of scope
}
Those rules are pretty strict, but maybe that's the only way to have a safe OnStack. Maybe I forgot some detail and those rules aren't even strict enough.
|
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | Am Thu, 20 Sep 2012 12:06:28 +0200 schrieb "monarch_dodra" <monarchdodra@gmail.com>: > On Thursday, 20 September 2012 at 08:10:36 UTC, Namespace wrote: > > You're right. > > This is my next try: http://dpaste.dzfl.pl/02b32d33 > > Do you have anything else to say? :) > > I think it looks good, but I'm unsure about "move", or allowing pass by value: > > Classes can't be memcopied the way structs can: Class may have default constructors, or copy constructors, which would be totally ignored by a memcopy. For example, if your class had a "RefCounted" member, its postblit would never be called, and it would then be "over destroyed": > > -------- > class A > { > RefCounted!int rf; > this() > { > rf.RefCounted.ensureInitialized(); > rf = 5; > } > } > > void main() > { > A a = new A(); > OnStack!A osa = OnStack!A.move(a); > } > -------- > core.exception.InvalidMemoryOperationError > -------- > Here, osa makes a binary copy of the RefCounted, so the count > stays at 1. > Then, when osa is destroyed, it deletes the RefCounted's store. > However, when a is destroyed, it still has a pointer to the > (deleted) store, creating the Error... > > I think "move" has to go, because classes are just not moveable. pass by value can stay, if and only if, T gives a copy constructor. Or NO constructors (in which case a memcopy should be the same as a default copy). http://dlang.org/struct.html D classes do not really have copy constructors. You could assume that if a constructor has only one argument and it's of the same type as the class, it's a copy constructor. But that's a pure convention then, nothing than could be enforced in any way. Copying classes is dangerous, and problems can also happen without constructors: ---------- class A { void* handle; ~this() { if(handle) free(handle); } } { auto a = OnStack!A(); a.handle = someHandle; auto b = a; //copy } //end of scope, someHandle is freed twice ---------- This can even happen if the class does not keep any reference types. The example would also be valid with a file handle (uint). |
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | On Thursday, 20 September 2012 at 10:20:24 UTC, Johannes Pfau wrote: > http://dlang.org/struct.html > D classes do not really have copy constructors. You could assume that > if a constructor has only one argument and it's of the same type as the class, it's a copy constructor. True... the term "copy constructor" is not 100% accurate, it is just "a constructor that takes the same type" A a = new A(); //Creates a new A A b = a; //Binds to the existing A A c = new A(a); //Constructs a new A, form an old A. > But that's a pure convention then, > nothing than could be enforced in any way. Copying classes is > dangerous, and problems can also happen without constructors: > [SNIP] Yes, that is a good point. I could find ways to make it crash even with a POD class, so I guess we could relax the condition to "don't ever memcpy a class: They aren't designed for that. Bad! Bad! Don't do it!" I'm learning from this thread. |
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | Namespace:
> is it also possible to move an existing object from the heap to the stack?
What's the point of doing it?
Bye,
bearophile
|
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | So I should disable the copy ctor (@disable this(this)) and drop move, right? As you can See if I pass a OnStack to function/class i'm using .get all the Time. The only other method IMO would be to pass it as OnStack by value and Store it in the other class also as OnStack, right? @bearophiole: just to Know if something lile this is possible. |
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Thursday, 20 September 2012 at 12:32:03 UTC, Namespace wrote: > So I should disable the copy ctor (@disable this(this)) and drop move, right? Yes, but at that point, what you have is scoped!T re-implemented :/ > As you can See if I pass a OnStack to function/class i'm using .get all the Time. You could "alias get this". This way, your OnStack will call cast as a T implicitly. Again, this is what scoped!T does. > The only other method IMO would be to pass it as OnStack by value and Store it in the other class also as OnStack, right? Yes, but that would require a copy contructor "this(this)", which we have actually ruled out. You can pass the T itself thanks to the implicit cast to T, but you can't pass an actual OnStack object. |
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Thursday, 20 September 2012 at 14:02:01 UTC, monarch_dodra wrote: > On Thursday, 20 September 2012 at 12:32:03 UTC, Namespace wrote: >> So I should disable the copy ctor (@disable this(this)) and drop move, right? > Yes, but at that point, what you have is scoped!T re-implemented :/ > >> As you can See if I pass a OnStack to function/class i'm using .get all the Time. > You could "alias get this". This way, your OnStack will call cast as a T implicitly. Again, this is what scoped!T does. > >> The only other method IMO would be to pass it as OnStack by value and Store it in the other class also as OnStack, right? > > Yes, but that would require a copy contructor "this(this)", which we have actually ruled out. You can pass the T itself thanks to the implicit cast to T, but you can't pass an actual OnStack object. http://dpaste.dzfl.pl/edit/361a54eb With [code] @disable this(this); [/code] this don't work (as expected). But with the copy ctor but without ".get" you earn a segmentation fault (as you can see). So you can disable the copy ctor but without using .get you're not get what you want. Even with scoped, but scoped's getter name is too long. |
September 20, 2012 Re: move object from heap to stack | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Thursday, 20 September 2012 at 14:09:29 UTC, Namespace wrote:
> http://dpaste.dzfl.pl/edit/361a54eb
> With
> [code]
> @disable this(this);
> [/code]
> this don't work (as expected). But with the copy ctor but without ".get" you earn a segmentation fault (as you can see). So you can disable the copy ctor but without using .get you're not get what you want. Even with scoped, but scoped's getter name is too long.
Wrong link.
|
Copyright © 1999-2021 by the D Language Foundation