www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to allocate arrays of objects?

reply cy <dlang verge.info.tm> writes:
The following program segfaults for me, compiling it with 
dmdv2.070 as well as the latest git. I must be doing it wrong. 
There's a way to specify class construction, or emplace, or 
something. But I can't find it! How do I deal with arrays of 
objects?

class A {
	int stuff;
}

void main()
{
	A[] as = new A[2];
	assert(as.length==2);
	as[0].stuff = 42;
}

Looking at it in gdb, the program segfaults on "A[] as = new 
A[2]" and never reaches "as[0].stuff = 42". But removing 
"as[0].stuff = 42" causes the program to stop segfaulting! 
assert(as.length == 2) doesn't get reached either.
Feb 10 2016
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Thursday, 11 February 2016 at 04:07:18 UTC, cy wrote:
 The following program segfaults for me, compiling it with 
 dmdv2.070 as well as the latest git. I must be doing it wrong. 
 There's a way to specify class construction, or emplace, or 
 something. But I can't find it! How do I deal with arrays of 
 objects?

 class A {
 	int stuff;
 }

 void main()
 {
 	A[] as = new A[2];
 	assert(as.length==2);
 	as[0].stuff = 42;
 }

 Looking at it in gdb, the program segfaults on "A[] as = new 
 A[2]" and never reaches "as[0].stuff = 42". But removing 
 "as[0].stuff = 42" causes the program to stop segfaulting! 
 assert(as.length == 2) doesn't get reached either.
You've allocated space for two class references, but you haven't actually allocated any class instances. This means both as[0] and as[1] are null, hence your segfault.
Feb 10 2016
prev sibling parent reply cy <dlang verge.info.tm> writes:
On Thursday, 11 February 2016 at 04:07:18 UTC, cy wrote:

 	A[] as = new A[2];
 	assert(as.length==2);
 	as[0].stuff = 42;
Oh, I get it. `as` is an array of 2 pointers to A objects, both pointers set to null. So I need to say like: as[0..$] = new A(); before accessing .stuff on as[0]. Still no clue why it segfaulted on the allocation though, rather than the statement with the null dereference. Hidden optimization?
Feb 10 2016
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 11 February 2016 at 04:31:12 UTC, cy wrote:
 as[0..$] = new A();

 before accessing .stuff on as[0].
Loop through it and allocate each one rather than trying to do it in a one liner like that.
 Still no clue why it segfaulted on the allocation though, 
 rather than the statement with the null dereference. Hidden 
 optimization?
The debug info sometimes shows the previous line instead of the current line. I betcha if you put some other random thing in between like a writeln() it would show that new thing as the line number it failed on. I think it is the address of the crash shows the last instruction actually finished but I'm not sure.
Feb 10 2016
parent reply Jacob Carlborg <doob me.com> writes:
On 2016-02-11 05:34, Adam D. Ruppe wrote:
 On Thursday, 11 February 2016 at 04:31:12 UTC, cy wrote:
 as[0..$] = new A();

 before accessing .stuff on as[0].
Loop through it and allocate each one rather than trying to do it in a one liner like that.
What about this? as[] = new A(); Or will that allocate a new one for each element? -- /Jacob Carlborg
Feb 11 2016
parent Meta <jared771 gmail.com> writes:
On Thursday, 11 February 2016 at 09:02:30 UTC, Jacob Carlborg 
wrote:
 On 2016-02-11 05:34, Adam D. Ruppe wrote:
 On Thursday, 11 February 2016 at 04:31:12 UTC, cy wrote:
 as[0..$] = new A();

 before accessing .stuff on as[0].
Loop through it and allocate each one rather than trying to do it in a one liner like that.
What about this? as[] = new A(); Or will that allocate a new one for each element?
import std.stdio; class Test { int n; int m; } void main() { auto testArr = new Test[](5); testArr[] = new Test(); foreach (ref test; testArr) { writeln(cast(void*)test); } } Output: 2A41010 2A41010 2A41010 2A41010 2A41010 Not really surprising, I guess. You can always do `generate(() => new Test()).take(5).array`.
Feb 11 2016
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On Thursday, 11 February 2016 at 04:31:12 UTC, cy wrote:
 Oh, I get it. `as` is an array of 2 pointers to A objects, both 
 pointers set to null. So I need to say like:

 as[0..$] = new A();

 before accessing .stuff on as[0].
Pedantically, no. It's an array of two class references. I don't think it's helpful to think of class references as pointers. That's just an implementation detail.
 Still no clue why it segfaulted on the allocation though, 
 rather than the statement with the null dereference. Hidden 
 optimization?
You said,
 removing "as[0].stuff = 42" causes the program to stop 
 segfaulting!
Which indicates that was where the segfault was happening. The debugger was just stopping before that.
Feb 10 2016