10

In D, all array literals are dynamic arrays, and are therefore allocated by the GC.

Even in this simple example:

int[3] a = [10, 20, 30];

The array is heap-allocated and then copied into a.

How are you supposed to initialise a static array without heap-allocation?

You could do it manually:

int[3] a = void;
a[0] = 10;
a[1] = 20;
a[2] = 30;

But this is tedious at best.

Is there a better way?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
  • I had no idea about this, I assumed local static arrays were allocated on the stack. :S – Andrej Mitrović Jul 20 '11 at 17:39
  • 1
    @Andrej: Yeah, surprised the hell out of me when I first found out. Apparently Don tried to convince Walter to make array literals static, but Walter is against it (can't find the thread atm). I imagine this could be a "gotcha" that haunts D for a while. – Peter Alexander Jul 20 '11 at 17:45
  • 1
    Also, this is exactly the type of thing which makes GC-less D totally impractical. It's just too damn easy to allocate memory without knowing about it. – Peter Alexander Jul 20 '11 at 17:46
  • Making array literal static by definition may be a problem but there is no reason the compiler couldn't optimize away the gc-allocate in that case, even make it a required optimization. – BCS Sep 14 '11 at 14:07

5 Answers5

9
static const int[3] a = [10, 20, 30];

This will place a constant copy in the data segment. You can create a copy on the stack (that doesn't involve a heap allocation) with a simple assignment (auto copy = a;).

Vladimir Panteleev
  • 24,651
  • 6
  • 70
  • 114
3

I think if you could declare the literal as immutable globally, then use that as the initializer, there's no heap allocation -- but I may be wrong, I'm not sure.

user541686
  • 205,094
  • 128
  • 528
  • 886
1

2017 UPDATE: In any recent version of DMD, using an array initializer on a static array no longer allocates, even if the static array is a local variable (ie stack-allocated).

You can verify this yourself by creating a function where a static array is initialized, and then marking the function as @nogc and observing whether or not it compiles. Example:

import std.random;
import std.stdio;
int[4] testfunc(int num) @nogc
{
    return [0, 1, num, 3];
}

int main()
{
    int[4] arr = testfunc(uniform(0, 15));
    writeln(arr);
    return 0;
}

Since testfunc() compiles despite being @nogc, we know that the array initializer does not allocate.

Lewis
  • 1,310
  • 1
  • 15
  • 28
1

I think you might be a bit mistaken: in http://www.digitalmars.com/d/2.0/arrays.html#static-init-static

Static Initialization of Static Arrays

Static initalizations are supplied by a list of array element values enclosed in [ ]. The values can be optionally preceded by an index and a :. If an index is not supplied, it is set to the previous index plus 1, or 0 if it is the first value.

-snip-

These arrays are static when they appear in global scope. Otherwise, they need to be marked with const or static storage classes to make them static arrays.

with code example

int[3] a = [ 1:2, 3 ]; // a[0] = 0, a[1] = 2, a[2] = 3

that means that const a[3] = [10, 20, 30]; won't/shouldn't allocate anything on the heap

ratchet freak
  • 47,288
  • 5
  • 68
  • 106
  • To clarify, I'm talking about local arrays, not global ones. Sorry, I should have stated that. Also, I don't want the array to be const or static. – Peter Alexander Jul 19 '11 at 18:37
1

It's just a compiler bug. I saw it in DMD's bugzilla. It should be fixed by now (DMD 2.055).

Gor
  • 11
  • 1