Thread overview
How to allocate arrays of objects?
Feb 11, 2016
cy
Feb 11, 2016
Mike Parker
Feb 11, 2016
cy
Feb 11, 2016
Adam D. Ruppe
Feb 11, 2016
Jacob Carlborg
Feb 11, 2016
Meta
Feb 11, 2016
Mike Parker
February 11, 2016
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.
February 11, 2016
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.
February 11, 2016
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?
February 11, 2016
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.
February 11, 2016
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.
February 11, 2016
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
February 11, 2016
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`.