Jump to page: 1 2
Thread overview
Accessing Dynamic Arrays - best approach?
Mar 15, 2005
AEon
Mar 15, 2005
Regan Heath
Mar 15, 2005
AEon
Mar 15, 2005
Regan Heath
Mar 15, 2005
Regan Heath
Mar 15, 2005
AEon
Mar 16, 2005
Regan Heath
Mar 15, 2005
Russ Lewis
Mar 16, 2005
Derek Parnell
Mar 16, 2005
AEon
Mar 16, 2005
AEon
Mar 16, 2005
Regan Heath
Mar 16, 2005
AEon
Mar 16, 2005
Regan Heath
Mar 16, 2005
Regan Heath
March 15, 2005
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
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
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
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
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
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
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
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
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
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