www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - No bounds checking for dynamic arrays at compile time?

reply "Pacoup" <etiennelg gmail.com> writes:
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.
Dec 12 2012
next sibling parent reply "Mehrdad" <wfunction hotmail.com> writes:
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?
language.
Dec 12 2012
parent reply "Pacoup" <etiennelg gmail.com> writes:
On Thursday, 13 December 2012 at 04:26:52 UTC, Mehrdad wrote:

 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?
Dec 12 2012
parent kenji hara <k.hara.pg gmail.com> writes:
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:


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?
Dec 12 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Dec 12 2012
parent reply "Marco Nembrini" <marco.nembrini.co gmail.com> writes:
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?
Dec 12 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
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.
Dec 12 2012
prev sibling next sibling parent reply "Chris Cain" <clcain uncg.edu> writes:
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.
Dec 12 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
Dec 13 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/13/2012 1:38 AM, bearophile wrote:
 To spot at compile-time situations like:


 void main() {
      int[5] x;
      x[$] = 1;
      enum size_t n = 2;
      x[$ + n] = 2;
 }
The compiler does that already.
 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
 }
I just don't see the point in adding flow analysis for that, and it'll ding you at runtime anyway. There are a lot more interesting things that flow analysis can do.
Dec 13 2012
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 void main() {
     int[5] x;
     x[$] = 1;
     enum size_t n = 2;
     x[$ + n] = 2;
 }
The compiler does that already.
I am compiling that little program with dmd -w test.d And I see no compilation errors. See also here, it gives a run-time error: http://dpaste.dzfl.pl/a62a10aa
 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
 }
I just don't see the point in adding flow analysis for that,
I think that doesn't require flow analysis.
 and it'll ding you at runtime anyway.
This thread is about spotting mistakes at compile-time, that is one of the main advantages of having a static typing in the first place. Bye, bearophile
Dec 13 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/13/2012 2:40 AM, bearophile wrote:
 Walter Bright:

 void main() {
     int[5] x;
     x[$] = 1;
     enum size_t n = 2;
     x[$ + n] = 2;
 }
The compiler does that already.
I am compiling that little program with dmd -w test.d And I see no compilation errors.
Well, it should for those cases.
 See also here, it gives a run-time error:
 http://dpaste.dzfl.pl/a62a10aa


 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
 }
I just don't see the point in adding flow analysis for that,
I think that doesn't require flow analysis.
Yeah, it does, unless you care to put in the compiler a long list of special cases. For example, what about $+$, n+$, $+$-$+1, $<<n, etc.? These sort of turn into whack-a-mole games.
 and it'll ding you at runtime anyway.
This thread is about spotting mistakes at compile-time, that is one of the main advantages of having a static typing in the first place.
Since the bug is caught anyway, such is an extremely low priority because it's got such a low payoff.
Dec 13 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 Well, it should for those cases.
OK, then I'll split that enhancement request into a bug report.
 Yeah, it does, unless you care to put in the compiler a long 
 list of special cases. For example, what about $+$, n+$, 
 $+$-$+1, $<<n, etc.? These sort of turn into whack-a-mole games.
I agree that putting lot of similar special cased tests in the compiler is a bad idea (also because code like $+$-$+1 is very uncommon). But can't the already present expression range analysis be used to cover some simple but common enough bugs?
 Since the bug is caught anyway, such is an extremely low 
 priority because it's got such a low payoff.
If that's true then why aren't you programming in Python? :-) Spotting mistakes at compile time is usually better because the sooner you find bugs, the less problems they cause. And because compile-time tests work on all code paths, while run-time tests only work on the code actively run (so bugs in uncommonly run code paths sometimes do not get caught, and maybe are caught much later by a client running the code). This is one of the main advantages of static typing over unit-testing. Bye, bearophile
Dec 13 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/13/2012 3:07 AM, bearophile wrote:
 I agree that putting lot of similar special cased tests in the compiler is a
bad
 idea (also because code like $+$-$+1 is very uncommon).
 But can't the already present expression range analysis be used to cover some
 simple but common enough bugs?
I've seen no evidence that these are "common enough".
 Since the bug is caught anyway, such is an extremely low priority because it's
 got such a low payoff.
If that's true then why aren't you programming in Python? :-) Spotting mistakes at compile time is usually better because the sooner you find bugs, the less problems they cause.
Although that is an advantage to static typing, it is hardly the only advantage. Static typing has a tremendous advantage in generating high performance code.
Dec 13 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/13/2012 11:40 AM, bearophile wrote:
 ...

 This thread is about spotting mistakes at compile-time, that is one of
 the main advantages of having a static typing in the first place.
 ...
Static code analysis also works when there is no static type checking.
Dec 13 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-12-13 10:54, Walter Bright wrote:

 I just don't see the point in adding flow analysis for that, and it'll
 ding you at runtime anyway
What about code that is only executed at compile time? -- /Jacob Carlborg
Dec 13 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/13/2012 4:05 AM, Jacob Carlborg wrote:
 On 2012-12-13 10:54, Walter Bright wrote:

 I just don't see the point in adding flow analysis for that, and it'll
 ding you at runtime anyway
What about code that is only executed at compile time?
CTFE would catch it.
Dec 13 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-12-13 22:26, Walter Bright wrote:

 CTFE would catch it.
Didn't you just say that flow analysis is needed for that? -- /Jacob Carlborg
Dec 13 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 14, 2012 08:34:44 Jacob Carlborg wrote:
 On 2012-12-13 22:26, Walter Bright wrote:
 CTFE would catch it.
Didn't you just say that flow analysis is needed for that?
No. You'd get a RangeError in CTFE just like you'd get at runtime. It's just that the function is being run at compile time instead of runtime. What would require flow analysis would be to statically determine that there was an indexing problem. It's the difference between examining the code to determine whether it has a problem and running it to see if it has a problem. - Jonathan M Davis
Dec 14 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/13/2012 11:34 PM, Jacob Carlborg wrote:
 On 2012-12-13 22:26, Walter Bright wrote:

 CTFE would catch it.
Didn't you just say that flow analysis is needed for that?
CTFE executes at compile time, no flow analysis is needed for that. DFA is something very different - it "executes" all paths simultaneously.
Dec 14 2012
next sibling parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
On Friday, 14 December 2012 at 08:40:59 UTC, Walter Bright wrote:
 On 12/13/2012 11:34 PM, Jacob Carlborg wrote:
 On 2012-12-13 22:26, Walter Bright wrote:

 CTFE would catch it.
Didn't you just say that flow analysis is needed for that?
CTFE executes at compile time, no flow analysis is needed for that. DFA is something very different - it "executes" all paths simultaneously.
What is the issue with flow analysis and D? Even on the toy compiler I had to create back in the university we implemented flow analysis for a few use cases. So the question is if toy university compilers have flow analysis why not having it in D? -- Paulo
Dec 14 2012
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Dec 14, 2012 at 04:08:09PM +0100, Paulo Pinto wrote:
 On Friday, 14 December 2012 at 08:40:59 UTC, Walter Bright wrote:
On 12/13/2012 11:34 PM, Jacob Carlborg wrote:
On 2012-12-13 22:26, Walter Bright wrote:

CTFE would catch it.
Didn't you just say that flow analysis is needed for that?
CTFE executes at compile time, no flow analysis is needed for that. DFA is something very different - it "executes" all paths simultaneously.
What is the issue with flow analysis and D? Even on the toy compiler I had to create back in the university we implemented flow analysis for a few use cases. So the question is if toy university compilers have flow analysis why not having it in D?
[...] Yeah I'm curious about this too. I also have implemented basic flow analysis in a compiler project in university. For the simple cases, it doesn't complicate the compiler that much at all. For a sophisticated compiler such as DMD, basic flow analysis would almost seem trivial. (But then again, it may add performance bottlenecks that I'm unaware of -- this was before I learnt the hard way that hotspots often aren't actually where you think they are.) T -- Acid falls with the rain; with love comes the pain.
Dec 14 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/14/2012 7:08 AM, Paulo Pinto wrote:
 So the question is if toy university compilers have flow analysis why not
having
 it in D?
The compiler does do full data flow analysis in the optimizer pass. But, by then, it is intermediate code not D code.
Dec 14 2012
parent Paulo Pinto <pjmlp progtools.org> writes:
Am 15.12.2012 03:56, schrieb Walter Bright:
 On 12/14/2012 7:08 AM, Paulo Pinto wrote:
 So the question is if toy university compilers have flow analysis why
 not having
 it in D?
The compiler does do full data flow analysis in the optimizer pass. But, by then, it is intermediate code not D code.
Ah ok. I am used to see it being done on the AST level, before doing further passes. -- Paulo
Dec 15 2012
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/14/12 3:40 AM, Walter Bright wrote:
 On 12/13/2012 11:34 PM, Jacob Carlborg wrote:
 On 2012-12-13 22:26, Walter Bright wrote:

 CTFE would catch it.
Didn't you just say that flow analysis is needed for that?
CTFE executes at compile time, no flow analysis is needed for that. DFA is something very different - it "executes" all paths simultaneously.
And then there's a other technique called "abstract execution" which is in between them! Andrei
Dec 14 2012
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 13 December 2012 at 09:38:18 UTC, bearophile wrote:
 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.

 [SNIP]

 Bye,
 bearophile
I guess you still have to keep in mind that in C, out of bounds access is undefined behavior, and may not error during run-time. This makes out of bounds access a real bane to find C, and tons (excessive?) effort have been expanded to avoid it. In comparison, D will assert on the first out of bounds access, and you'll immediately see where the problem lies, with no undefined behavior or whatnot. While I wouldn't disagree that having the compiler do it statically would be a good thing, it's not as critically needed as it would be in C. I guess I'm just saying the "cost to payback" ratio is not as high as in C.
Dec 13 2012
prev sibling parent reply "Chris Cain" <clcain uncg.edu> writes:
On Thursday, 13 December 2012 at 09:38:18 UTC, bearophile wrote:
 That program seems to have a bug, unless the signature of foo 
 becomes (ref int[]).
Indeed. I'm learning how to type on a new keyboard, so most of my brain power is being spent on figuring out where the keys are. It took me over 40 minutes to type that whole message. :( I said it right in my head, fwiw.
 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.
The problem is that it can't solve anything but the most basic of errors in code. This type of analysis will simultaneously be computationally expensive and useless in _real_ code. My point is that, ultimately, run time problems have to be dealt with at run time. I wouldn't mind this suggestion except for the fact that it will take away human resources from much more useful endeavors (not to mention increasing compilation time). Many suggestions I see the value in... but I see almost none here (as I explained, it won't do anything in non-trivial code that you might actually see using dynamic arrays).
Dec 13 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Dec 13, 2012 at 05:31:05PM +0100, Chris Cain wrote:
 On Thursday, 13 December 2012 at 09:38:18 UTC, bearophile wrote:
[...]
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.
The problem is that it can't solve anything but the most basic of errors in code. This type of analysis will simultaneously be computationally expensive and useless in _real_ code. My point is that, ultimately, run time problems have to be dealt with at run time. I wouldn't mind this suggestion except for the fact that it will take away human resources from much more useful endeavors (not to mention increasing compilation time). Many suggestions I see the value in... but I see almost none here (as I explained, it won't do anything in non-trivial code that you might actually see using dynamic arrays).
Yeah, I think this is a case of premature optimization, a very tempting trap to fall into for efficiency-minded people (like myself). Many of these "optimizations" actually hurt, rather than help. Like you said, making the compiler detect dynamic array length at compile-time is non-trivial -- in fact, it amounts to solving the Halting Problem, which is unsolvable -- so the only practical cases that can be done are trivial and most likely nowhere near the performance bottleneck that makes optimization necessary in the first place. Definitely not worth the significant increase in compilation times. I used to be a big fan of optimizing everywhere, until one day I actually took the time to profile my code, and discovered to my great surprise that my hotspots were NOT where I thought they were. They were all the places where I didn't even think to look because they were so trivial and so obviously already "optimal". Which meant that 90% of my "optimization" efforts had been wasted on code that wasn't even important to optimize, while neglecting the real hotspots. (In fact, some of my "optimizations" turned out to actually degrade performance, because I eschewed a certain implementation technique as "slow" where it would have helped with the actual hotspots in the code. Not to mention wasting much of my time in thinking up clever ways of "optimizing", where a straightforward implementation would have sufficed.) I wouldn't be surprised if many (most?) programmers will be shocked to learn where the real hotspots in their code are, contrary to whatever preconceived notions they may have had. T -- A computer doesn't mind if its programs are put to purposes that don't match their names. -- D. Knuth
Dec 13 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
H. S. Teoh:

 Yeah, I think this is a case of premature optimization,
That part of the thread was not about compiler optimizations. It was about bug detection. Bye, bearophile
Dec 13 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/13/2012 9:40 AM, H. S. Teoh wrote:
 I wouldn't
 be surprised if many (most?) programmers will be shocked to learn where
 the real hotspots in their code are, contrary to whatever preconceived
 notions they may have had.
I can vouch for this. I've been programming for 35 years, and I still get gobsmacked by where the real bottleneck is. For errors, what I try to do is look at the kinds of patterns of error that are commonplace, and try to devise ways to head them off. Expending effort on better detection of errors that people don't make is a waste of time. (Note I said "better" detection. Errors still need to be detected.)
Dec 13 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 For errors, what I try to do is look at the kinds of patterns 
 of error that are commonplace, and try to devise ways to head 
 them off.
This was a bug commonly found, I think you accepted it, but it's not fixed yet. I hope it's not forgotten, it's a little breaking change: http://d.puremagic.com/issues/show_bug.cgi?id=5409 - - - - - - - - - - - - - - - - Some other common bug patterns: Issue http://d.puremagic.com/issues/show_bug.cgi?id=4407 class Foo { int x, y; this(int x_, int y_) { this.x = x; y = y; } } void main() {} - - - - - - - - - - - - - - - - Issue http://d.puremagic.com/issues/show_bug.cgi?id=3878 Arguments and members with the same name: class Foo { int x; this(int x) { x = x; } void inc(int x) { this.x += x; } } class Bar { int x; this() { x = 5; } } struct Spam { static int x; void inc(int x) { Spam.x += x; } } void main() {} - - - - - - - - - - - - - - - - Issue http://d.puremagic.com/issues/show_bug.cgi?id=5187 public class Foo { public int x = 10; } public class Test : Foo { public int x = 20; } void main() {} - - - - - - - - - - - - - - - - Issue http://d.puremagic.com/issues/show_bug.cgi?id=5212 class Foo { int[] args; this(int[] args_...) { args = args_; } } Foo foo() { return new Foo(1, 2, 3); // passes stack data to Foo } void main() { assert(foo().args == [1, 2, 3]); } - - - - - - - - - - - - - - - - Issue http://d.puremagic.com/issues/show_bug.cgi?id=8757 auto x1 = y1 ? z1 : w1; // OK auto x2 = x0 + (y1 ? z1 : w1); // OK auto x3 = (x0 + y1) ? z1 : w1; // OK auto x4 = x0 + y1 ? z1 : w1; // Not good auto x5 = y1 ? z1 : (y2 ? z2 : w2); // OK auto x6 = y1 ? z1 : y2 ? z2 : w2; // Not good - - - - - - - - - - - - - - - -
 Expending effort on better detection of errors that people 
 don't make is a waste of time.
I agree. Bugs 5409 and 8757 are demonstrably common in already debugged C/C++ code. Bug 5212 is a trap. Now this issue is fixed: http://d.puremagic.com/issues/show_bug.cgi?id=6883 So this code: void main() { int[5] x; x[x.length] = 1; x[$] = 1; enum size_t n = 2; x[x.length + n] = 2; x[$ + n] = 2; } Generates the errors: test.d(3): Error: array index 5 is out of bounds x[0 .. 5] test.d(4): Error: array index 5 is out of bounds x[0 .. 5] test.d(6): Error: array index 7 is out of bounds x[0 .. 5] test.d(7): Error: array index 7 is out of bounds x[0 .. 5] If I keep the same code but I replace x with a dynamic array no compile-time errors are generated: void main() { auto x = new int[5]; x[x.length] = 1; x[$] = 1; enum size_t n = 2; x[x.length + n] = 2; x[$ + n] = 2; } give the same compilation errors for all or part of those four Bye, bearophile
Dec 13 2012
prev sibling next sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
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.
Dec 12 2012
prev sibling parent reply "Gopan" <Gopan.Gopalakrishnan gmail.com> writes:
import std.stdio;

void main()
{
	int[3][2] matrix = [ [1,11,111], [2,22,222] ];

	foreach(int[5] row; matrix) //if int[3], there is no error.
	{
              foreach(x; row)
		write(x, "  ");
		
	     writeln();
	}
}

I get runtime error for the above code too.

Application error:
object.Exception src/rt/arraycat.d(31): lengths don't match for 
array copy


Why didn't I get a compilation error?  All the array sizes are 
known at compile time.  Right?
Dec 13 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Gopan:

 Why didn't I get a compilation error?  All the array sizes are 
 known at compile time.  Right?
The good Hara and Don have teamed and they have already written a patch and applied it: http://d.puremagic.com/issues/show_bug.cgi?id=6883 So if you are able to compile DMD you are able to test if the new patch works in your case too. Bye, bearophile
Dec 13 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
 So if you are able to compile DMD you are able to test if the 
 new patch works in your case too.
The answer was negative: http://d.puremagic.com/issues/show_bug.cgi?id=9150 Bye, bearophile
Dec 13 2012