www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - array construction without heap alloc

reply Frank Benoit <keinfarbton googlemail.com> writes:
With D1:

I have a function with this unchangable signature:

  void func( int[] a ){} // will not store the array ref

Now i want to pass in some non-const integer values:

  void bar( int a, int b ){
    func( [ a, b ] );
  }

My problem is, i want to do it without heap allocation. So I can do this:

  void bar( int a, int b ){
    int[2] arr;
    arr[0] = a;
    arr[1] = b;
    func( arr );
  }

This works, but the syntax sucks.
Any suggestions?
Dec 21 2007
next sibling parent reply 0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Frank Benoit wrote:
 My problem is, i want to do it without heap allocation. So I can do this:
 
   void bar( int a, int b ){
     int[2] arr;
     arr[0] = a;
     arr[1] = b;
     func( arr );
   }

I don't know, but I'd guess this would also not allocate heap: void bar( int a, int b ) { int[2] arr=[a,b]; func( arr ); } regards, frank
Dec 21 2007
parent reply 0ffh <frank frankhirsch.youknow.what.todo.net> writes:
I compiled this using D1 (DMD):

   void bar( int a, int b )
   {
     int[2] arr=[a,b];
     int brr;
     int[] crr;
     crr.length=2;
     func( arr );
     printf("%p %p\n",&arr,arr.ptr);
     printf("%p\n",&brr);
     printf("%p %p\n",&crr,crr.ptr);
   }

It gives me &arr==arr.ptr, which is near &brr and &crr,
while crr.ptr is somewhere completely different.
I suppose that kinda proofs it. =)
Hope it's helpful.

regards, frank
Dec 21 2007
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
0ffh schrieb:
 
 I compiled this using D1 (DMD):
 
   void bar( int a, int b )
   {
     int[2] arr=[a,b];
     int brr;
     int[] crr;
     crr.length=2;
     func( arr );
     printf("%p %p\n",&arr,arr.ptr);
     printf("%p\n",&brr);
     printf("%p %p\n",&crr,crr.ptr);
   }
 
 It gives me &arr==arr.ptr, which is near &brr and &crr,
 while crr.ptr is somewhere completely different.
 I suppose that kinda proofs it. =)
 Hope it's helpful.
 
 regards, frank

Sorry, but this does a heap allocation. I forgot to mention how i detect it. I used obj2asm to get the assembly of the object file. Using the array literal will cause a call to the d runtime _d_arrayliteralT function, which uses heap allocation. On IRC "Hxal" posted a template magic solution. It goes like this: struct StaticArray(T, size_t S){ T[S] array; } StaticArray!(typeof(T[0]), T.length) staticArray(T...)(T values){ StaticArray!(typeof(T[0]), T.length) x; foreach(i,v; values) x.array[i] = v; return x; } Usage is: void bar( int a, int b ){ func( staticArray( a, b ).array ) } I wonder why arrayliterals are allocated on the heap. You always have the .dup option.
Dec 22 2007
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Frank Benoit" <keinfarbton googlemail.com> wrote in message 
news:fkj3oe$2qcm$1 digitalmars.com...

 I wonder why arrayliterals are allocated on the heap.

Probably to prevent otherwise very common errors like: void foo(int x, int y) { someGlobal = [x, y]; } int[] bar(int x, int y) { return [x, y]; } i.e. escaping references to a locally-allocated array. Before anyone says "but the compiler could detect those", what about in this case: extern(C) someFunc(int* arr, int len); void myFunc(int x, int y) { auto arr = [x, y]; someFunc(arr.ptr, arr.length); } The compiler knows nothing about what someFunc does and can't tell if it stores that array away in some global variable or something, therefore it can't tell if this is legal code. (This is why side effects are bad, the FP programmers tell us..)
Dec 22 2007
next sibling parent Frank Benoit <keinfarbton googlemail.com> writes:
Jarrett Billingsley schrieb:
 "Frank Benoit" <keinfarbton googlemail.com> wrote in message 
 news:fkj3oe$2qcm$1 digitalmars.com...
 
 I wonder why arrayliterals are allocated on the heap.

Probably to prevent otherwise very common errors like: void foo(int x, int y) { someGlobal = [x, y]; } int[] bar(int x, int y) { return [x, y]; } i.e. escaping references to a locally-allocated array.

So it is exaclty the same situation how it is with pointers to local function in D1 compared to D2. In D1 you need to know what to do, in D2 there is no way around the heap.
Dec 22 2007
prev sibling next sibling parent 0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Jarrett Billingsley wrote:
 Before anyone says "but the compiler could detect those", what about in this 
 case:

It would be quite enough if it detected that it's initialising a static array on the stack, as in the example. That's what I'd have expected. regards, frank
Dec 22 2007
prev sibling parent 0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Jarrett Billingsley wrote:
 Before anyone says "but the compiler could detect those", what about in this 
 case:
 
 extern(C) someFunc(int* arr, int len);
 
 void myFunc(int x, int y)
 {
     auto arr = [x, y];
     someFunc(arr.ptr, arr.length);
 }
 
 The compiler knows nothing about what someFunc does and can't tell if it 
 stores that array away in some global variable or something, therefore it 
 can't tell if this is legal code.  (This is why side effects are bad, the FP 
 programmers tell us..) 

If I am not mistaken, your example here does the "bad thing" already, no matter if it allocates heap to initialise the variable or not. regards, frank
Dec 24 2007
prev sibling parent reply 0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Frank Benoit wrote:
 I wonder why arrayliterals are allocated on the heap.
 You always have the .dup option.

That's really unfortunate, especially as the array does quite definitely end up on the stack. So with a static array and an array literal you would get the worst of both worlds. I'll investigate that. regards, frank
Dec 22 2007
parent 0ffh <frank frankhirsch.youknow.what.todo.net> writes:
0ffh wrote:
 That's really unfortunate, especially as the array does
 quite definitely end up on the stack. So with a static
 array and an array literal you would get the worst of
 both worlds. I'll investigate that.

Yup, it seems to eat memory, that's a bad sign! Sorry for misleading you, but this is really unexpected! regards, frank
Dec 22 2007
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 21 Dec 2007 21:25:31 +0100, Frank Benoit wrote:

This below seems to work...

import std.stdio;
void func( int[] a )
{
    writefln("a's address = %08p", a.ptr); 
    
}

void bar( int a, int b ){
    int c;
    writefln("c's address = %08p", &c); 

    scope int[2]f = [a,b];
    func(f);
}

void main()
{
    bar(1,2);
}

However the syntax is not as neat as you'd like it I guess.

-- 
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell
Dec 22 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Derek Parnell" <derek psych.ward> wrote in message 
news:79knrjyy3vnp$.1vie66jlel0bb.dlg 40tude.net...

    scope int[2]f = [a,b];

It's syntactically legal, but it won't delete the array at the end of the scope. Dumb, I know.
Dec 22 2007