On Thursday, 27 August 2015 at 10:05:31 UTC, John Burton wrote:
I'm a c++ programmer trying to understand how memory allocation
works in D.
I created a struct and added a destructor to it. My
understanding is that structs have deterministic destructors -
they are called when the struct goes out of scope (unless it is
allocated with new).
Now if I put instances of the struct in a fixed size array
data[6] d;
d[3] = data(1, 2, 3);
then the destructor on all the contents is called when the
array goes out of scope.
However if I add them to a dynamic array...
data[] d;
d ~= data(1, 2, 3)
Then the destructor appears to be called at some random time
later. So it looks like it's the garbage collection that is
doing this. That seems to go against the specification of how
struct works... I'm not creating the item with "new" and as far
as I can tell the array is storing instances of objects, not
pointers to objects?
Is my understanding correct?
Is it documented anywhere how memory allocation works for this?
Is a dynamic array in fact storing an array of GC'd pointers to
the structs? Or something else...
With a local scope,
- a static array of data will have the destructors called on
exit because memory for the memebers is not allocated on the
GC-hep but on the stack frame.
- a dynamic array of data will have the destructors called on
next GC collection because the memory for the memebers is
allocated on the GC-heap.
- a dynamic array of pointer to data will have the destructors
called on next GC collection because the memory for the memebers
is allocated on the GC-heap.
you can see this in this small program. deactivate to commented
GC.collect to see the difference:
---
struct Foo {
long v0, v1;
~this(){writeln(typeof(this).stringof);}
}
void localteststatic(){
Foo[1] fl;
}
void localtestdynamic1(){
Foo[] fl;
fl.length = 1;
fl.length = 0;
}
void localtestdynamic2(){
Foo* [] fl;
fl ~= new Foo(1);
}
void localtestdynamic3(){
Foo[] fl;
fl.length = 1;
fl.length = 0;
}
void main(string[] args)
{
import core.memory;
localteststatic; writeln("done local test static");
localtestdynamic3; writeln("done local test dynamic 3");
//GC.collect;
localtestdynamic1; writeln("done local test dynamic 1");
//GC.collect;
localtestdynamic2; writeln("done local test dynamic 2");
//GC.collect;
}
---
Also for the second question:
* fl[]: each element has a .sizeof 16 (long .size_of * 2)
* fl* []: each element has a .sizeof size_t.sizeof (this a
pointer so 4 or 8).