Jump to page: 1 24  
Page
Thread overview
No bounds checking for dynamic arrays at compile time?
Dec 13, 2012
Pacoup
Dec 13, 2012
Mehrdad
Dec 13, 2012
Pacoup
Dec 13, 2012
kenji hara
Dec 13, 2012
Walter Bright
Dec 13, 2012
Marco Nembrini
Dec 13, 2012
Walter Bright
Dec 13, 2012
Chris Cain
Dec 13, 2012
bearophile
Dec 13, 2012
Walter Bright
Dec 13, 2012
bearophile
Dec 13, 2012
Walter Bright
Dec 13, 2012
bearophile
Dec 13, 2012
Walter Bright
Dec 13, 2012
Timon Gehr
Dec 13, 2012
Jacob Carlborg
Dec 13, 2012
Walter Bright
Dec 14, 2012
Jacob Carlborg
Dec 14, 2012
Jonathan M Davis
Dec 14, 2012
Walter Bright
Dec 14, 2012
Paulo Pinto
Dec 14, 2012
H. S. Teoh
Dec 15, 2012
Walter Bright
Dec 15, 2012
Paulo Pinto
Dec 13, 2012
monarch_dodra
Dec 13, 2012
Chris Cain
Dec 13, 2012
H. S. Teoh
Dec 13, 2012
bearophile
Dec 13, 2012
Walter Bright
Dec 13, 2012
bearophile
Dec 13, 2012
SomeDude
Dec 13, 2012
Gopan
Dec 13, 2012
bearophile
Dec 13, 2012
bearophile
December 13, 2012
I've been newly exploring D for a very short while now, and, exploring Array functionality, I came upon this funny bit of code off of a badly written tutorial.

import std.stdio;

void main()
{
   int[] intArray;
	
   intArray[0] = 42;
   intArray[1] = 54;
   intArray[2] = 91;

   writefln("The length of intArray is %d.", intArray.length);
}

This compiles, believe it or not, and doesn't throw any errors or warnings whatsoever, but obviously for people who know D, this will throw a core.exception.RangeError: Range violation when run.

Why? Because Dynamic Arrays in D are not dynamic à-la-JavaScript, they can just be resized. The missing line comes directly after the array declaration:

intArray.length = 3;

Now, given that doing int[] myArray initializes a dynamic array with length 0, why is there no bounds checking on this? Why is the compiler not even throwing a warning telling me the dynamic array's length has not been initialized or that I'm trying to access data which is potentially out of bounds?

Static arrays throw out of bounds errors on compilation when there's a mismatch, but why not dynamic arrays?

I thought D was supposed to be a language allowing safer programming than C. This isn't very convincing for such an elementary feature of the language.
December 13, 2012
On Thursday, 13 December 2012 at 04:11:10 UTC, Pacoup wrote:
> I've been newly exploring D for a very short while now, and, exploring Array functionality, I came upon this funny bit of code off of a badly written tutorial.
>
> import std.stdio;
>
> void main()
> {
>    int[] intArray;
> 	
>    intArray[0] = 42;
>    intArray[1] = 54;
>    intArray[2] = 91;
>
>    writefln("The length of intArray is %d.", intArray.length);
> }
>
> This compiles, believe it or not, and doesn't throw any errors or warnings whatsoever, but obviously for people who know D, this will throw a core.exception.RangeError: Range violation when run.
>
> Why?

It's C++ philosophy imposed on the C#-like aspects of the language.
December 13, 2012
On Thursday, 13 December 2012 at 04:26:52 UTC, Mehrdad wrote:
>
> It's C++ philosophy imposed on the C#-like aspects of the language.

That's not a rationale for not having bounds checking on dynamic arrays at compile time. How is this making the language better? Is there a technical limitation which explains this?
December 13, 2012
On 12/12/2012 8:11 PM, Pacoup wrote:
> Static arrays throw out of bounds errors on compilation when there's a mismatch,
> but why not dynamic arrays?

Because the length of dynamic arrays is unknown at compile time.

December 13, 2012
Because detecting that requires code flow analysis.
Note that it is completely different from CTFE.

Kenji Hara

2012/12/13 Pacoup <etiennelg@gmail.com>

> On Thursday, 13 December 2012 at 04:26:52 UTC, Mehrdad wrote:
>
>>
>> It's C++ philosophy imposed on the C#-like aspects of the language.
>>
>
> That's not a rationale for not having bounds checking on dynamic arrays at compile time. How is this making the language better? Is there a technical limitation which explains this?
>


December 13, 2012
On Thursday, 13 December 2012 at 04:54:33 UTC, Walter Bright wrote:
> On 12/12/2012 8:11 PM, Pacoup wrote:
>> Static arrays throw out of bounds errors on compilation when there's a mismatch,
>> but why not dynamic arrays?
>
> Because the length of dynamic arrays is unknown at compile time.

That's true in general, but in this particular case you could see at compile time that the array is never resized and give a warning. Obvously as soon as there is one resizing somewhere with some run-time value you cannot do it anymore.

I wonder if that would be useful?
December 13, 2012
On 12/12/2012 9:09 PM, Marco Nembrini wrote:
> On Thursday, 13 December 2012 at 04:54:33 UTC, Walter Bright wrote:
>> On 12/12/2012 8:11 PM, Pacoup wrote:
>>> Static arrays throw out of bounds errors on compilation when there's a mismatch,
>>> but why not dynamic arrays?
>>
>> Because the length of dynamic arrays is unknown at compile time.
>
> That's true in general, but in this particular case you could see at compile
> time that the array is never resized and give a warning. Obvously as soon as
> there is one resizing somewhere with some run-time value you cannot do it anymore.
>
> I wonder if that would be useful?

You'd have to add data flow analysis to the front end, and you'd reap very little useful error messages out of it.

Note that this example came from a tutorial, not real code.
December 13, 2012
On Thursday, 13 December 2012 at 04:11:10 UTC, Pacoup wrote:
> Static arrays throw out of bounds errors on compilation when there's a mismatch, but why not dynamic arrays?
>
> I thought D was supposed to be a language allowing safer programming than C. This isn't very convincing for such an elementary feature of the language.

Dynamic arrays are arrays whose length is set at run time. Thus, it makes sense that they would give a run time error when they fail.

Plus, trying to determine whether the length of an array is exceeded at compile-time would be a hard problem. Sure, in this instance it's easy to see that the length of the array is exceeded... but then again, you aren't doing anything you couldn't use a static array for either.

Consider:

void main() {
   int[] arr;
   foo(arr);
   arr[0] = 2;
}

Should this spit out a compile time error? You can't say without knowing what 'foo' does. If I say foo means this:

void foo(int[] array) {
   int len;
   readf(" %s", &len);
   array.length = len;
}

Well, now it depends on what len is. This could easily be reading from a file where you know len is always greater than 0, but the compiler doesn't know. So does it fail to compile until you put some pragmas in to assure the compiler that its going to be okay... or what?

Of course, regardless, you're going to need it to throw an exception if you're wrong because things change and you might read in a bad file that sets len to 0.

In general, the compiler can't know ahead of time whether accessing a dynamic array will be out of bounds without running it. Exceptions are designed to handle these types of programming errors.
December 13, 2012
On Thursday, 13 December 2012 at 04:11:10 UTC, Pacoup wrote:
> I've been newly exploring D for a very short while now, and, exploring Array functionality, I came upon this funny bit of code off of a badly written tutorial.
>
> import std.stdio;
>
> void main()
> {
>    int[] intArray;
> 	
>    intArray[0] = 42;
>    intArray[1] = 54;
>    intArray[2] = 91;
>
>    writefln("The length of intArray is %d.", intArray.length);
> }
>
> This compiles, believe it or not, and doesn't throw any errors or warnings whatsoever, but obviously for people who know D, this will throw a core.exception.RangeError: Range violation when run.
>
> Why? Because Dynamic Arrays in D are not dynamic à-la-JavaScript, they can just be resized. The missing line comes directly after the array declaration:
>
> intArray.length = 3;
>
> Now, given that doing int[] myArray initializes a dynamic array with length 0, why is there no bounds checking on this? Why is the compiler not even throwing a warning telling me the dynamic array's length has not been initialized or that I'm trying to access data which is potentially out of bounds?
>
> Static arrays throw out of bounds errors on compilation when there's a mismatch, but why not dynamic arrays?
>
> I thought D was supposed to be a language allowing safer programming than C. This isn't very convincing for such an elementary feature of the language.

I guess the author of the tutorial should be made aware of his mistake, before he spreads bad lessons to newcomers.
December 13, 2012
Chris Cain:

> Consider:
>
> void main() {
>    int[] arr;
>    foo(arr);
>    arr[0] = 2;
> }
>
> Should this spit out a compile time error? You can't say without knowing what 'foo' does. If I say foo means this:
>
> void foo(int[] array) {
>    int len;
>    readf(" %s", &len);
>    array.length = len;
> }
>
> Well, now it depends on what len is.

That program seems to have a bug, unless the signature of foo becomes (ref int[]). A bit smarter compiler should see that.


> In general, the compiler can't know ahead of time whether accessing a dynamic array will be out of bounds without running it.

Right, but there are several cases where a little smarter compiler is able to see at compile-time that something bad is present in the code.

----------------------

Walter:

> You'd have to add data flow analysis to the front end, and you'd reap very little useful error messages out of it.

From my usages of a lint tool in C, that's able to perform that flow analysis, I have seen that it spots several out of array bound mistakes in the code statically.


> Note that this example came from a tutorial, not real code.

It's from a tutorial, and I agree well tested code usually doesn't have those problems, but when you are writing code you often do some mistakes (that later you fix), so having a compiler that helps a little is useful to speed up the coding and debugging itself. It's better to spot mistakes as early as possible.

See also what I have suggested time ago:
http://d.puremagic.com/issues/show_bug.cgi?id=6884
http://d.puremagic.com/issues/show_bug.cgi?id=6883

To spot at compile-time situations like:


void main() {
    int[5] x;
    x[$] = 1;
    enum size_t n = 2;
    x[$ + n] = 2;
}


void main() {
    int[] x = new int[5];
    x[$] = 1; // easy
    x[x.length] = 1; // idem
    enum size_t n = 2;
    x[$ + n] = 2; // not too much hard if n is unsigned
    x[x.length + n] = 2; // idem
}

Bye,
bearophile
« First   ‹ Prev
1 2 3 4