Arrays of structs

BBasile via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Aug 27 03:36:47 PDT 2015


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).


More information about the Digitalmars-d-learn mailing list