Thread overview
Initialisation of static immutable arrays
Oct 06, 2010
Denis Koroskin
Oct 06, 2010
Denis Koroskin
October 06, 2010
I have a program that uses an immutable array, the contents of which are known at compile time.  Thus, ideally, I want it to be placed in the .rodata segment of the program.

Firstly, I seem to remember reading that using an array literal in D will always result in a heap allocation.  Is this correct?

Secondly, if the above is not true, how can I verify that the array in the following piece of code isn't allocated and/or copied anew every time the program runs, or even worse, every time foo() is called?

  void foo()
  {
      static immutable int[3] = [1, 2, 3];
  }

I know, RTFAsm, but some help with that would be appreciated. ;)

Thirdly, intuition tells me that when the array is immutable, the 'static' shouldn't have an effect.  But experiments (i.e. printing the adress of the array) indicate that it does.  Is there some reason for this, or is it just a shortcoming of the compiler?

-Lars
October 06, 2010
On Wed, 06 Oct 2010 10:16:45 +0000, Lars T. Kyllingstad wrote:

>       static immutable int[3] = [1, 2, 3];

..should of course be

  static immutable int[3] a = [1, 2, 3];

-Lars
October 06, 2010
On Wed, 06 Oct 2010 06:16:45 -0400, Lars T. Kyllingstad <public@kyllingen.nospamnet> wrote:

> I have a program that uses an immutable array, the contents of which are
> known at compile time.  Thus, ideally, I want it to be placed in
> the .rodata segment of the program.
>
> Firstly, I seem to remember reading that using an array literal in D will
> always result in a heap allocation.  Is this correct?

Yes.  There is no way to create an immutable array besides a string in read only memory.  Even enums will result in array literals being created on the heap whenever you refer to them (there's a bug related to this somewhere).

> Secondly, if the above is not true, how can I verify that the array in
> the following piece of code isn't allocated and/or copied anew every time
> the program runs, or even worse, every time foo() is called?
>
>   void foo()
>   {
>       static immutable int[3] = [1, 2, 3];
>   }

Actually, static probably will prevent it from being created every time foo is called.  I don't think there's a way to prevent it from being created every time the program is run.

> I know, RTFAsm, but some help with that would be appreciated. ;)
>
> Thirdly, intuition tells me that when the array is immutable, the
> 'static' shouldn't have an effect.  But experiments (i.e. printing the
> adress of the array) indicate that it does.  Is there some reason for
> this, or is it just a shortcoming of the compiler?

Of course.  If you realize that the expression [1,2,3] is not immutable, then it makes sense.

Another example to help you think about it:

void foo(int x)
{
   immutable int[3] = [1,2,x];
}

This must be run on every call of foo, because x can vary.

BTW, I'm all for making array literals immutable.  You can always make runtime-allocated arrays via a library function.

-Steve
October 06, 2010
On Wed, 06 Oct 2010 15:39:48 +0400, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> BTW, I'm all for making array literals immutable.  You can always make runtime-allocated arrays via a library function.
>
> -Steve

I second that!
October 06, 2010
On Wed, 06 Oct 2010 07:39:48 -0400, Steven Schveighoffer wrote:

> On Wed, 06 Oct 2010 06:16:45 -0400, Lars T. Kyllingstad <public@kyllingen.nospamnet> wrote:
> 
> [...]
> 
>> Secondly, if the above is not true, how can I verify that the array in the following piece of code isn't allocated and/or copied anew every time the program runs, or even worse, every time foo() is called?
>>
>>   void foo()
>>   {
>>       static immutable int[3] = [1, 2, 3];
>>   }
> 
> Actually, static probably will prevent it from being created every time foo is called.  I don't think there's a way to prevent it from being created every time the program is run.

Does anyone know a way to verify this?  (If it is in fact created every time the function runs, I'll change it to a module-level array initialised in a 'static this()' instead.)


>> I know, RTFAsm, but some help with that would be appreciated. ;)
>>
>> Thirdly, intuition tells me that when the array is immutable, the 'static' shouldn't have an effect.  But experiments (i.e. printing the adress of the array) indicate that it does.  Is there some reason for this, or is it just a shortcoming of the compiler?
> 
> Of course.  If you realize that the expression [1,2,3] is not immutable, then it makes sense.
> 
> Another example to help you think about it:
> 
> void foo(int x)
> {
>     immutable int[3] = [1,2,x];
> }
> 
> This must be run on every call of foo, because x can vary.

I don't think that is a very good reason.  The compiler could detect the special (and, might I add, common) case where an array literal whose contents are known at compile time is assigned to an immutable variable, and treat it as immutable even though [1,2,3] is formally of type int[].


> BTW, I'm all for making array literals immutable.  You can always make runtime-allocated arrays via a library function.

I completely agree.

-Lars
October 06, 2010
On Wed, 06 Oct 2010 16:21:08 +0400, Lars T. Kyllingstad <public@kyllingen.nospamnet> wrote:

> On Wed, 06 Oct 2010 07:39:48 -0400, Steven Schveighoffer wrote:
>
>> On Wed, 06 Oct 2010 06:16:45 -0400, Lars T. Kyllingstad
>> <public@kyllingen.nospamnet> wrote:
>>
>> [...]
>>
>>> Secondly, if the above is not true, how can I verify that the array in
>>> the following piece of code isn't allocated and/or copied anew every
>>> time the program runs, or even worse, every time foo() is called?
>>>
>>>   void foo()
>>>   {
>>>       static immutable int[3] = [1, 2, 3];
>>>   }
>>
>> Actually, static probably will prevent it from being created every time
>> foo is called.  I don't think there's a way to prevent it from being
>> created every time the program is run.
>
> Does anyone know a way to verify this?  (If it is in fact created every
> time the function runs, I'll change it to a module-level array
> initialised in a 'static this()' instead.)
>

It's static so it allocates only once. But the following:

immutable int[3] = [1, 2, 3];

always allocates, but I see no reason why it should.
October 06, 2010
On Wed, 06 Oct 2010 08:21:08 -0400, Lars T. Kyllingstad <public@kyllingen.nospamnet> wrote:

> On Wed, 06 Oct 2010 07:39:48 -0400, Steven Schveighoffer wrote:
>> Of course.  If you realize that the expression [1,2,3] is not immutable,
>> then it makes sense.
>>
>> Another example to help you think about it:
>>
>> void foo(int x)
>> {
>>     immutable int[3] = [1,2,x];
>> }
>>
>> This must be run on every call of foo, because x can vary.
>
> I don't think that is a very good reason.  The compiler could detect the
> special (and, might I add, common) case where an array literal whose
> contents are known at compile time is assigned to an immutable variable,
> and treat it as immutable even though [1,2,3] is formally of type int[].

I'm not saying it is a good explanation, but it is why the compiler does it.  Any time an array literal occurs anywhere is an allocation.  I have never seen a case where the compiler optimizes that out.  Given that context, the behavior makes sense.

I don't think any allocation should occur here, even if array literals are not made immutable, because that allocation is going to be thrown away immediately.  I agree this should be special-cased.  I believe there are several bugs on array literals and allocations.

-Steve