digitalmars.D.learn - destroy(someStruct)
- John Colvin (30/30) Sep 20 2014 import core.stdc.stdio;
- Chris Cain (21/51) Sep 20 2014 That's how structs work, so yes. Structs will always run their
- monarch_dodra (7/37) Sep 21 2014 Destroy leaves your struct in its T.init state, and T.init should
import core.stdc.stdio; struct S { ~this() { printf("%x\n".ptr, &this); } } void main() { S* sp = new S; destroy(*sp); S s; destroy(s); auto sa = new S[2]; foreach(ref s_; sa) destroy(s_); } output: 4002dff0 bfa89a70 4002dfe0 4002dfe1 bfa89a70 Note the double destruction of s Its seems that calling destroy on a stack-allocated struct is a no-no (unless you have a re-entrant destructor). The other two examples seem OK though. Am I in dangerous territory? Will I see unexpected double-destructions in some cases?
Sep 20 2014
On Saturday, 20 September 2014 at 22:46:10 UTC, John Colvin wrote:import core.stdc.stdio; struct S { ~this() { printf("%x\n".ptr, &this); } } void main() { S* sp = new S; destroy(*sp); S s; destroy(s); auto sa = new S[2]; foreach(ref s_; sa) destroy(s_); } output: 4002dff0 bfa89a70 4002dfe0 4002dfe1 bfa89a70 Note the double destruction of s Its seems that calling destroy on a stack-allocated struct is a no-no (unless you have a re-entrant destructor). The other two examples seem OK though. Am I in dangerous territory? Will I see unexpected double-destructions in some cases?That's how structs work, so yes. Structs will always run their destructor at the end of their scope if stack allocated. Pointers to structs are currently working somewhat in an unexpected manner (that is, AFAIK, they don't destruct even when deallocated, but theoretically they could be set up to do so). Arrays to structs will probably never see proper destruction (there was a conversation about it somewhere here in the forums between myself and another poster and they convinced me that it's not really going to be possible since, as far as the GC is concerned, it can never know which structs have been constructed/used in a given section of memory, of which an array/slice is a subset of, and must be destructed. So at the very least, you may end up destructing a struct's init state if a greedy implementation is ever done). I personally always make my destructors work on already destructed structs/init'd structs and that's my official recommendation on the matter. You can get away with a struct that cannot do so iff you can guarantee that it will never be manually destructed and it will only ever be stack allocated (which, in general, is probably not a safe assumption to make).
Sep 20 2014
On Saturday, 20 September 2014 at 22:46:10 UTC, John Colvin wrote:import core.stdc.stdio; struct S { ~this() { printf("%x\n".ptr, &this); } } void main() { S* sp = new S; destroy(*sp); S s; destroy(s); auto sa = new S[2]; foreach(ref s_; sa) destroy(s_); } output: 4002dff0 bfa89a70 4002dfe0 4002dfe1 bfa89a70 Note the double destruction of s Its seems that calling destroy on a stack-allocated struct is a no-no (unless you have a re-entrant destructor). The other two examples seem OK though. Am I in dangerous territory? Will I see unexpected double-destructions in some cases?Destroy leaves your struct in its T.init state, and T.init should always be destroyable. So even though the destroyer gets called twice, you should be perfectly safe. FYI, "move" relies on this mechanism: it sets object state to T.init, to make sure the later stack destruction has no side effect.
Sep 21 2014