Thread overview
Array-initialization
Oct 09, 2008
Hendrik Renken
Oct 09, 2008
torhu
Oct 10, 2008
Hendrik Renken
October 09, 2008
Hi,

i have a question regarding array-initialization.


consider:

struct STRUCT
{
    byte[] data;
}


STRUCT foo(byte[] myData)
{
    STRUCT* s = new STRUCT(myData);
}


do i now create a struct with an array on the heap and then drop the array and assign to the array-pointer the array "myData"? If yes, how can i avoid the creation and deletion of the array "data" in the first place? Am i right, that the variable "data" only holds a pointer to the real array?

regards,
hendrik


October 09, 2008
Hendrik Renken wrote:
> Hi,
> 
> i have a question regarding array-initialization.
> 
> 
> consider:
> 
> struct STRUCT
> {
>      byte[] data;
> }
> 
> 
> STRUCT foo(byte[] myData)
> {
>      STRUCT* s = new STRUCT(myData);
> }
> 
> 
> do i now create a struct with an array on the heap and then drop the array and assign to the array-pointer the array "myData"? If yes, how can i avoid the creation and deletion of the array "data" in the first place? Am i right, that the variable "data" only holds a pointer to the real array?

"data" is a dynamic array reference, so STRUCT is really just this:

struct STRUCT
{
  size_t length;
  byte* ptr;
}


So "data" is just a number of elements and a pointer to the first one. When you do "new STRUCT(myData)", you're only allocating room for that.  There's no room for array contents  allocated, just the reference.

If you do writeln(STRUCT.sizeof); it will always say 8 on a 32-bit system, same goes for data.sizeof.


Your example should probably look like this, as there's no point in heap allocating small structs:


STRUCT foo(byte[] myData)
{
     STRUCT s = STRUCT(myData);
}
October 10, 2008
> "data" is a dynamic array reference, so STRUCT is really just this:
> 
> struct STRUCT
> {
>   size_t length;
>   byte* ptr;
> }


This explains everything. Thanks.


>  So "data" is just a number of elements and a pointer to the first one.
> When you do "new STRUCT(myData)", you're only allocating room for that.  There's no room for array contents  allocated, just the reference.
> 
> If you do writeln(STRUCT.sizeof); it will always say 8 on a 32-bit system, same goes for data.sizeof.
> 
> 


let me modify your example:

> STRUCT foo(byte[] myData)
> {
>      STRUCT s = STRUCT(myData);
       return s;
> }


will the content of s now be copied when it is returned?


>
> Your example should probably look like this, as there's no point in heap
> allocating small structs:
>

what means small? below how many bytes?
October 10, 2008
On Fri, Oct 10, 2008 at 4:42 AM, Hendrik Renken <funsheep@gmx.net> wrote:

> let me modify your example:
>
>> STRUCT foo(byte[] myData)
>> {
>>     STRUCT s = STRUCT(myData);
>
>       return s;
>>
>> }
>
>
> will the content of s now be copied when it is returned?

Yes, the contents of *s* will be copied (that is, the array reference), but *not* the array data itself.

>> Your example should probably look like this, as there's no point in heap allocating small structs:
>>
>
> what means small? below how many bytes?

It's subjective, but a struct that's only 4-8 bytes can be easily passed around in registers and there is therefore no need to heap-allocate it.  Of course on a 64-bit platform even a 16-byte struct is small.
October 10, 2008
"Hendrik Renken" wrote
>
>> "data" is a dynamic array reference, so STRUCT is really just this:
>>
>> struct STRUCT
>> {
>>   size_t length;
>>   byte* ptr;
>> }
>
>
> This explains everything. Thanks.
>
>
>>  So "data" is just a number of elements and a pointer to the first one.
>> When you do "new STRUCT(myData)", you're only allocating room for that.
>> There's no room for array contents  allocated, just the reference.
>>
>> If you do writeln(STRUCT.sizeof); it will always say 8 on a 32-bit system, same goes for data.sizeof.
>>
>>
>
>
> let me modify your example:
>
>> STRUCT foo(byte[] myData)
>> {
>>      STRUCT s = STRUCT(myData);
>        return s;
>> }
>
>
> will the content of s now be copied when it is returned?

the pointer will be copied.  If you want a copy of the data, try this:

STRUCT s = STRUCT(myData.dup);

This duplicates the data before setting the pointer.  array.dup is a shallow copy, so if you are duping an array of pointers, only the pointers get copied, not the data they point to.  If you want a 'deep' copy, you have to loop and do it yourself at this point.

>
>
> >
> > Your example should probably look like this, as there's no point in heap allocating small structs:
> >
>
> what means small? below how many bytes?

All heap allocations are a minimum of 16 bytes.  So if you are allocating a struct that just contains a pointer and a length (i.e. an array), that is an 8-byte struct on a 32 bit system.  That means 100% overhead...  Plus heap allocations require grabbing a global thread mutex, finding a suitable allocation block, possibly running a garbage collect cycle.  They are slow, much slower than using a stack allocated struct.

Of course if you are copying the data, a dup is going to do a heap allocation, so not much is gained by putting your struct on the stack. However, you probably don't *need* to use the heap for the struct data, I'd recommend against it.

-Steve