digitalmars.D - No bounds checking for dynamic arrays at compile time?
- Pacoup (30/30) Dec 12 2012 I've been newly exploring D for a very short while now, and,
- Mehrdad (3/21) Dec 12 2012 It's C++ philosophy imposed on the C#-like aspects of the
- Pacoup (4/6) Dec 12 2012 That's not a rationale for not having bounds checking on dynamic
- kenji hara (4/11) Dec 12 2012 Because detecting that requires code flow analysis.
- Walter Bright (2/4) Dec 12 2012 Because the length of dynamic arrays is unknown at compile time.
- Marco Nembrini (7/12) Dec 12 2012 That's true in general, but in this particular case you could see
- Walter Bright (4/14) Dec 12 2012 You'd have to add data flow analysis to the front end, and you'd reap ve...
- Chris Cain (34/39) Dec 12 2012 Dynamic arrays are arrays whose length is set at run time. Thus,
- bearophile (37/57) Dec 13 2012 That program seems to have a bug, unless the signature of foo
- Walter Bright (5/20) Dec 13 2012 I just don't see the point in adding flow analysis for that, and it'll d...
- bearophile (12/29) Dec 13 2012 I am compiling that little program with
- Walter Bright (7/35) Dec 13 2012 Yeah, it does, unless you care to put in the compiler a long list of spe...
- bearophile (17/23) Dec 13 2012 I agree that putting lot of similar special cased tests in the
- Walter Bright (4/13) Dec 13 2012 Although that is an advantage to static typing, it is hardly the only ad...
- Timon Gehr (2/6) Dec 13 2012 Static code analysis also works when there is no static type checking.
- Jacob Carlborg (4/6) Dec 13 2012 What about code that is only executed at compile time?
- Walter Bright (2/6) Dec 13 2012 CTFE would catch it.
- Jacob Carlborg (4/5) Dec 13 2012 Didn't you just say that flow analysis is needed for that?
- Jonathan M Davis (7/11) Dec 14 2012 No. You'd get a RangeError in CTFE just like you'd get at runtime. It's ...
- Walter Bright (3/6) Dec 14 2012 CTFE executes at compile time, no flow analysis is needed for that. DFA ...
- Paulo Pinto (8/18) Dec 14 2012 What is the issue with flow analysis and D?
- H. S. Teoh (12/32) Dec 14 2012 [...]
- Walter Bright (3/5) Dec 14 2012 The compiler does do full data flow analysis in the optimizer pass. But,...
- Paulo Pinto (6/12) Dec 15 2012 Ah ok.
- Andrei Alexandrescu (4/13) Dec 14 2012 And then there's a other technique called "abstract execution" which is
- monarch_dodra (13/19) Dec 13 2012 I guess you still have to keep in mind that in C, out of bounds
- Chris Cain (17/22) Dec 13 2012 Indeed. I'm learning how to type on a new keyboard, so most of my
- H. S. Teoh (29/45) Dec 13 2012 Yeah, I think this is a case of premature optimization, a very tempting
- bearophile (5/6) Dec 13 2012 That part of the thread was not about compiler optimizations. It
- Walter Bright (7/11) Dec 13 2012 I can vouch for this. I've been programming for 35 years, and I still ge...
- bearophile (102/107) Dec 13 2012 This was a bug commonly found, I think you accepted it, but it's
- SomeDude (3/34) Dec 12 2012 I guess the author of the tutorial should be made aware of his
- Gopan (18/18) Dec 13 2012 import std.stdio;
- bearophile (8/10) Dec 13 2012 The good Hara and Don have teamed and they have already written a
- bearophile (4/6) Dec 13 2012 The answer was negative:
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
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
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
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
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
On Thursday, 13 December 2012 at 04:54:33 UTC, Walter Bright wrote:On 12/12/2012 8:11 PM, Pacoup wrote: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?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
On 12/12/2012 9:09 PM, Marco Nembrini wrote:On Thursday, 13 December 2012 at 04:54:33 UTC, Walter Bright wrote: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.On 12/12/2012 8:11 PM, Pacoup wrote: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?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
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
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
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
Walter Bright: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/a62a10aavoid main() { int[5] x; x[$] = 1; enum size_t n = 2; x[$ + n] = 2; }The compiler does that already.I think that doesn't require flow analysis.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.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
On 12/13/2012 2:40 AM, bearophile wrote:Walter Bright:Well, it should for those cases.I am compiling that little program with dmd -w test.d And I see no compilation errors.void main() { int[5] x; x[$] = 1; enum size_t n = 2; x[$ + n] = 2; }The compiler does that already.See also here, it gives a run-time error: http://dpaste.dzfl.pl/a62a10aaYeah, 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 think that doesn't require flow analysis.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,Since the bug is caught anyway, such is an extremely low priority because it's got such a low payoff.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.
Dec 13 2012
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
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".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.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.
Dec 13 2012
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
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 anywayWhat about code that is only executed at compile time? -- /Jacob Carlborg
Dec 13 2012
On 12/13/2012 4:05 AM, Jacob Carlborg wrote:On 2012-12-13 10:54, Walter Bright wrote:CTFE would catch it.I just don't see the point in adding flow analysis for that, and it'll ding you at runtime anywayWhat about code that is only executed at compile time?
Dec 13 2012
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
On Friday, December 14, 2012 08:34:44 Jacob Carlborg wrote:On 2012-12-13 22:26, Walter Bright wrote: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 DavisCTFE would catch it.Didn't you just say that flow analysis is needed for that?
Dec 14 2012
On 12/13/2012 11:34 PM, Jacob Carlborg wrote:On 2012-12-13 22:26, Walter Bright wrote:CTFE executes at compile time, no flow analysis is needed for that. DFA is something very different - it "executes" all paths simultaneously.CTFE would catch it.Didn't you just say that flow analysis is needed for that?
Dec 14 2012
On Friday, 14 December 2012 at 08:40:59 UTC, Walter Bright wrote:On 12/13/2012 11:34 PM, Jacob Carlborg wrote: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? -- PauloOn 2012-12-13 22:26, Walter Bright wrote:CTFE executes at compile time, no flow analysis is needed for that. DFA is something very different - it "executes" all paths simultaneously.CTFE would catch it.Didn't you just say that flow analysis is needed for that?
Dec 14 2012
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:[...] 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.On 12/13/2012 11:34 PM, Jacob Carlborg wrote: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?On 2012-12-13 22:26, Walter Bright wrote:CTFE executes at compile time, no flow analysis is needed for that. DFA is something very different - it "executes" all paths simultaneously.CTFE would catch it.Didn't you just say that flow analysis is needed for that?
Dec 14 2012
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
Am 15.12.2012 03:56, schrieb Walter Bright:On 12/14/2012 7:08 AM, Paulo Pinto wrote:Ah ok. I am used to see it being done on the AST level, before doing further passes. -- PauloSo 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 15 2012
On 12/14/12 3:40 AM, Walter Bright wrote:On 12/13/2012 11:34 PM, Jacob Carlborg wrote:And then there's a other technique called "abstract execution" which is in between them! AndreiOn 2012-12-13 22:26, Walter Bright wrote:CTFE executes at compile time, no flow analysis is needed for that. DFA is something very different - it "executes" all paths simultaneously.CTFE would catch it.Didn't you just say that flow analysis is needed for that?
Dec 14 2012
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, bearophileI 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
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
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:[...]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. KnuthRight, 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
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
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
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
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
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
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
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