View mode: basic / threaded / horizontal-split · Log in · Help
March 15, 2005
Accessing Dynamic Arrays - best approach?
Playing around with dynamic arrays like:

   int[] d;   // Dynamic Array has no size! Just declared, not initialized
yet?!
              // -> d.length = 0 

   d[10] = 3; // Error: Access Violation

but with a "dummy call":    

   d.length = 1;

suddenly I can access elements in the array, even though I am exceeding the
length limits?

   d[10] = 3; // Works!

I would have expected that a "d.length = 11;" is required for "d[10] = 3;" to
work?


Put differently, once a dynamic array has been declared (int[] d;), how does one
go about to let you access elements in the array?


Let's say you have a dynamic array, and you want to copy 10 numbers (that are
calculated one by one and do *not* already exist) into it. Would you do this?:

   int[] d;
   d.length = 1;  // First call, dynamic array would only need to hold 1
number
   d[0] = 3;      // 1st number

next number:

   d.length ++;
   d[1] = 8;     // 2nd number

IOW would one resize (re-length) the dynamic array every time?

Obviously one could probably upsize the array in larger steps, e.g. if you know
you will have 1000 numbers, you could "d.length = d.length + 100;", but would
the above be the "good" way to go?

AEon
March 15, 2005
Re: Accessing Dynamic Arrays - best approach?
On Tue, 15 Mar 2005 22:07:34 +0000 (UTC), AEon <AEon_member@pathlink.com>  
wrote:
> Playing around with dynamic arrays like:
>
>     int[] d;   // Dynamic Array has no size! Just declared, not  
> initialized
> yet?!
>                // -> d.length = 0
>
>     d[10] = 3; // Error: Access Violation
>
> but with a "dummy call":
>
>     d.length = 1;
>
> suddenly I can access elements in the array, even though I am exceeding  
> the
> length limits?
>
>     d[10] = 3; // Works!

I get an "ArrayBoundsError" when I compile either of these examples with  
no flags, and "Access Violation" if I compile them with -release.

> I would have expected that a "d.length = 11;" is required for "d[10] =  
> 3;" to
> work?

It is.

> Put differently, once a dynamic array has been declared (int[] d;), how  
> does one
> go about to let you access elements in the array?

1. set the length.
2. use [],for,while,do,foreach to access elements.

> Let's say you have a dynamic array, and you want to copy 10 numbers  
> (that are
> calculated one by one and do *not* already exist) into it. Would you do  
> this?:
>
>     int[] d;
>     d.length = 1;  // First call, dynamic array would only need to hold 1
> number
>     d[0] = 3;      // 1st number
>
> next number:
>
>     d.length ++;
>     d[1] = 8;     // 2nd number
>
> IOW would one resize (re-length) the dynamic array every time?
>
> Obviously one could probably upsize the array in larger steps, e.g. if  
> you know
> you will have 1000 numbers, you could "d.length = d.length + 100;", but  
> would
> the above be the "good" way to go?

If you know you need 1000 numbers, you can write:

d.length = 1000;
foreach(int i, inout int v; d) {
  //i is the index into the array
  v = //calculation goes here
}

Regan
March 15, 2005
Re: Accessing Dynamic Arrays - best approach?
Regan Heath says...

>> Playing around with dynamic arrays like:
>>
>>     int[] d;
>>     d[10] = 3; // Error: Access Violation
>>
>> but with a "dummy call":
>>
>>     d.length = 1;
>>
>> suddenly I can access elements in the array, even though I am exceeding  
>> the length limits?
>>
>>     d[10] = 3; // Works!
>
>I get an "ArrayBoundsError" when I compile either of these examples with  
>no flags, and "Access Violation" if I compile them with -release.

Just tested this again. Using any of these parameter sets in my makefile:

DFLAGS=-I.
DFLAGS=-O -I.
DFLAGS=-w -O -I.
DFLAGS=-w -O -inline -I.

yields the "Error: ArrayBoundsError test(266)" you mentioned.

DFLAGS=-w -O -release -inline -I.

compiles cleanly for me. And running the test program will show the proper
values. No crash. This seems to mean that when developping, one should *not* use
the -release switch since that "hides" certain bugs, e.g. turns off full
checking?


>> I would have expected that a "d.length = 11;" is required for "d[10] =  
>> 3;" to work?
>It is.

Good... the above made me nervous, and I was starting to wonder if array
boundary checks are actually done.


>> Put differently, once a dynamic array has been declared (int[] d;), how  
>> does one go about to let you access elements in the array?
>1. set the length.
>2. use [],for,while,do,foreach to access elements.

Ok... so setting the length is a *must*.

AEon
March 15, 2005
Re: Accessing Dynamic Arrays - best approach?
AEon wrote:
> Playing around with dynamic arrays like:
> 
>     int[] d;   // Dynamic Array has no size! Just declared, not initialized
> yet?!
>                // -> d.length = 0 
> 
>     d[10] = 3; // Error: Access Violation
> 
> but with a "dummy call":    
> 
>     d.length = 1;
> 
> suddenly I can access elements in the array, even though I am exceeding the
> length limits?
> 
>     d[10] = 3; // Works!

You're correct that this code is not valid.

You're obviously compiling with -release, because, otherwise, D would do 
bounds checking for you and you would get an ArrayBoundsError.  My guess 
why it works is that D has allocated some memory for the array, and 
while the allocation is small, theOScan only do access protection on a 
page level.  Thus, when you overflow the array, you are reading memory 
which you are not supposed to touch - but there is no way to force you 
not to.
March 15, 2005
Re: Accessing Dynamic Arrays - best approach?
On Tue, 15 Mar 2005 22:59:14 +0000 (UTC), AEon <AEon_member@pathlink.com>  
wrote:
>>> Playing around with dynamic arrays like:
>>>
>>>     int[] d;
>>>     d[10] = 3; // Error: Access Violation
>>>
>>> but with a "dummy call":
>>>
>>>     d.length = 1;
>>>
>>> suddenly I can access elements in the array, even though I am exceeding
>>> the length limits?
>>>
>>>     d[10] = 3; // Works!
>>
>> I get an "ArrayBoundsError" when I compile either of these examples with
>> no flags, and "Access Violation" if I compile them with -release.
>
> Just tested this again. Using any of these parameter sets in my makefile:
>
> DFLAGS=-I.
> DFLAGS=-O -I.
> DFLAGS=-w -O -I.
> DFLAGS=-w -O -inline -I.
>
> yields the "Error: ArrayBoundsError test(266)" you mentioned.
>
> DFLAGS=-w -O -release -inline -I.
>
> compiles cleanly for me. And running the test program will show the  
> proper
> values. No crash.

Can you attach your test code. I still get "Access Violation". I suspect  
it's a 'fluke', as in the memory referenced by d[10] just happens to be  
yours to modify, perhaps part of another variable.

> This seems to mean that when developping, one should *not* use
> the -release switch since that "hides" certain bugs, e.g. turns off full
> checking?

Yes. -release disables the runtime array bounds checks, and others.

>>> I would have expected that a "d.length = 11;" is required for "d[10] =
>>> 3;" to work?
>> It is.
>
> Good... the above made me nervous, and I was starting to wonder if array
> boundary checks are actually done.

Only when -release is not used.

>>> Put differently, once a dynamic array has been declared (int[] d;), how
>>> does one go about to let you access elements in the array?
>> 1. set the length.
>> 2. use [],for,while,do,foreach to access elements.
>
> Ok... so setting the length is a *must*.

Sort of, yes.. you can get an array with a valid length without setting it  
explicitly, eg.

int[] original = "12345"; //original.length is 5
int[] new;

new = original.dup;   //new.length is now 5
new = original[0..3]  //new.length is now 3

//note:
new[1] = 5; //will crash on linux, but not windows, as 'new' slices  
'original' which is static.

Regan
March 15, 2005
Re: Accessing Dynamic Arrays - best approach?
On Wed, 16 Mar 2005 12:08:27 +1300, Regan Heath <regan@netwin.co.nz> wrote:
> int[] original = "12345"; //original.length is 5
> int[] new;
>
> new = original.dup;   //new.length is now 5
> new = original[0..3]  //new.length is now 3
>
> //note:
> new[1] = 5; //will crash on linux, but not windows, as 'new' slices  
> 'original' which is static.

To clarify:

new = original.dup;
new[1] = 5;

will not crash. But:

new = original[0..3];
new[1] = 5;

might, depending on OS.

Regan
March 15, 2005
Re: Accessing Dynamic Arrays - best approach?
Regan Heath says...

>Can you attach your test code. I still get "Access Violation". I suspect  
>it's a 'fluke', as in the memory referenced by d[10] just happens to be  
>yours to modify, perhaps part of another variable.

<code>
import std.c.stdio;

int main (char[][] args)
{
printf("\n  Clearing dynamic arrays int[] d and d = null\n\n");

int[] d;
printf("   d.length = %d  (int[] d)\n", d.length);      

d.length = 1;
printf("   d.length = %d  (d.length = 11)\n", d.length);
printf("   d[10] = %d     (inits values!)\n", d[10]);

d[10] = 3;                          
printf("   d[10] = %d     (d[10] = 3)\n", d[10]);
d = null;
// printf("   d[10] = %d     (d = null)\n", d[10]); // Error: Access Violation

return 0;
}
</code>

(dmd 0.118, windows)
>dmd -w -release test3.d
E:\d\dmd\bin\..\..\dm\bin\link.exe test3,,,user32+kernel32/noi;

>test3

Clearing dynamic arrays int[] d and d = null

d.length = 0  (int[] d)
d.length = 1  (d.length = 11)
d[10] = 0     (inits values!)
d[10] = 3     (d[10] = 3)

As you can see d[10] access works when -release is turned on.


>dmd -w test3.d
E:\d\dmd\bin\..\..\dm\bin\link.exe test3,,,user32+kernel32/noi;

>test3

Clearing dynamic arrays int[] d and d = null

d.length = 0  (int[] d)
d.length = 1  (d.length = 11)
Error: ArrayBoundsError test3.d(12)  

A "normal" compile on the other hand shows the boundary violation.


>Sort of, yes.. you can get an array with a valid length without setting it  
>explicitly, eg.
>
>int[] original = "12345"; //original.length is 5
>int[] new;
>
>new = original.dup;   //new.length is now 5
>new = original[0..3]  //new.length is now 3

The length of 5 to me reads a bit strange, I would have assumed 1. And that you
can assign a string literal (what that the right term) to an int array is also
strange. Will test the above some more. BTW since IIRC "new" is a keyword, using
it as a variable is kinda evil :)

AEon
March 16, 2005
Re: Accessing Dynamic Arrays - best approach?
On Tue, 15 Mar 2005 22:07:34 +0000 (UTC), AEon wrote:

> Playing around with dynamic arrays like:
> 
>     int[] d;   // Dynamic Array has no size! Just declared, not initialized
> yet?!
>                // -> d.length = 0 
> 
>     d[10] = 3; // Error: Access Violation

Because at this point your array does not point to any RAM. 

> but with a "dummy call":    
> 
>     d.length = 1;

By doing this, D allocates at least enough RAM to hold one element and sets
the array to point to that RAM.

> suddenly I can access elements in the array, even though I am exceeding the
> length limits?
> 
>     d[10] = 3; // Works!
> 
> I would have expected that a "d.length = 11;" is required for "d[10] = 3;" to
> work?

If you compile with -release, DMD turns off checking for bad index values.
It instead assumes you know what you are doing. By luck, you got to access
some RAM that your application owned, but it wasn't necessarily owned by
the array itself.


> Put differently, once a dynamic array has been declared (int[] d;), how does one
> go about to let you access elements in the array?
> 
> Let's say you have a dynamic array, and you want to copy 10 numbers (that are
> calculated one by one and do *not* already exist) into it. Would you do this?:
> 
>     int[] d;
>     d.length = 1;  // First call, dynamic array would only need to hold 1
> number
>     d[0] = 3;      // 1st number
> 
> next number:
> 
>     d.length ++;
>     d[1] = 8;     // 2nd number
> 
> IOW would one resize (re-length) the dynamic array every time?

You could, but that is not the way I'd do it. I would do either ...

  d.length = 10;
  d[0] = 3;
  d[1] = 8;
  d[3] = ... etc...

or 
  d ~= 3;
  d ~= 8;
  d ~= ... etc ...


> Obviously one could probably upsize the array in larger steps, e.g. if you know
> you will have 1000 numbers, you could "d.length = d.length + 100;", but would
> the above be the "good" way to go?

You would probably select the method that made more sense for the
application. Presetting the length is fine if you know how many items you
are adding, but the concatenation method may be more useful when you don't
know how many items there will be.

-- 
Derek
Melbourne, Australia
16/03/2005 11:59:08 AM
March 16, 2005
Re: Accessing Dynamic Arrays - best approach?
On Tue, 15 Mar 2005 23:41:35 +0000 (UTC), AEon <AEon_member@pathlink.com>  
wrote:
> Regan Heath says...
>
>> Can you attach your test code. I still get "Access Violation". I suspect
>> it's a 'fluke', as in the memory referenced by d[10] just happens to be
>> yours to modify, perhaps part of another variable.
>
> <code>
> import std.c.stdio;
>
> int main (char[][] args)
> {
> printf("\n  Clearing dynamic arrays int[] d and d = null\n\n");
>
> int[] d;
> printf("   d.length = %d  (int[] d)\n", d.length);
>
> d.length = 1;
> printf("   d.length = %d  (d.length = 11)\n", d.length);
> printf("   d[10] = %d     (inits values!)\n", d[10]);
>
> d[10] = 3;
> printf("   d[10] = %d     (d[10] = 3)\n", d[10]);
> d = null;
> // printf("   d[10] = %d     (d = null)\n", d[10]); // Error: Access  
> Violation
>
> return 0;
> }
> </code>
>
> (dmd 0.118, windows)
>> dmd -w -release test3.d
> E:\d\dmd\bin\..\..\dm\bin\link.exe test3,,,user32+kernel32/noi;
>
>> test3
>
> Clearing dynamic arrays int[] d and d = null
>
> d.length = 0  (int[] d)
> d.length = 1  (d.length = 11)
> d[10] = 0     (inits values!)
> d[10] = 3     (d[10] = 3)
>
> As you can see d[10] access works when -release is turned on.

I now get the same results as you did. I would call this 'undefined'  
behaviour.
Perhaps Walter can shed some light? Perhaps arrays allocate a minimum size  
for efficiency?

>> Sort of, yes.. you can get an array with a valid length without setting  
>> it
>> explicitly, eg.
>>
>> int[] original = "12345"; //original.length is 5
>> int[] new;
>>
>> new = original.dup;   //new.length is now 5
>> new = original[0..3]  //new.length is now 3
>
> The length of 5 to me reads a bit strange, I would have assumed 1. And  
> that you
> can assign a string literal (what that the right term) to an int array  
> is also
> strange.

Doh! sorry, the code above will never compile.

 Will test the above some more. BTW since IIRC "new" is a
> keyword, using
> it as a variable is kinda evil :)

Yet another reason my code is illegal.

Let me try again:

char[] original = "12345";
char[] a;

a = original.dup;
a = original[0..3];

(same comments as before)

Regan
March 16, 2005
Re: Accessing Dynamic Arrays - best approach?
AEon wrote:

> next number:
> 
>     d.length ++;
>     d[1] = 8;     // 2nd number

As a side note, "d.length++;" is not allowed
(since you *might* use it to hurt yourself...)

One must do "d.length = d.length + 1;" instead.
Or just use "d ~= 8;", which is a lot easier ?

--anders
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home