digitalmars.D.learn - Iterating over 0..T.max
- Magnus Lie Hetland (18/18) Mar 09 2011 In a (template) data structure I'm working on, I had the following think...
- Kai Meyer (47/62) Mar 09 2011 I don't see how that works in dmd2, and I don't have much experience
- Magnus Lie Hetland (10/12) Mar 10 2011 Derp. I didn't mean bool -- I was talking about byte. (Which should
- bearophile (4/7) Mar 10 2011 Please show a complete minimal program that gives you problem. (I have f...
- Steven Schveighoffer (20/26) Mar 10 2011 void main()
- bearophile (4/9) Mar 10 2011 http://d.puremagic.com/issues/show_bug.cgi?id=5725
In a (template) data structure I'm working on, I had the following thinko: auto a = new T[n]; foreach (T i, ref e; a) { e = i; } Then I instantiated it with T=bool, and n=256. Infinite loop, of course -- the problem being that i wraps around to 0 after the last iteration. Easily fixed, and not that much of a problem (given that I caught it) -- I'll just use e = cast(T) i. (Of course, even with that solution, I'd get wrap problems if n=257, but I just want to make sure I allow T.max as a size.) But I'm wondering: given D's excellent valua range propagations and overflow checking, would it be possible to catch this special case (i.e., detect when the array can be too long for the index type)? Or are any other safeguards possible to prevent this sort of thing? -- Magnus Lie Hetland http://hetland.org
Mar 09 2011
On 03/09/2011 09:09 AM, Magnus Lie Hetland wrote:In a (template) data structure I'm working on, I had the following thinko: auto a = new T[n]; foreach (T i, ref e; a) { e = i; } Then I instantiated it with T=bool, and n=256. Infinite loop, of course -- the problem being that i wraps around to 0 after the last iteration. Easily fixed, and not that much of a problem (given that I caught it) -- I'll just use e = cast(T) i. (Of course, even with that solution, I'd get wrap problems if n=257, but I just want to make sure I allow T.max as a size.) But I'm wondering: given D's excellent valua range propagations and overflow checking, would it be possible to catch this special case (i.e., detect when the array can be too long for the index type)? Or are any other safeguards possible to prevent this sort of thing?I don't see how that works in dmd2, and I don't have much experience with dmd1, so I'll admit that this may be different on dmd1. I get compilation errors with your code: import std.stdio; void main() { make_new!(bool)(256); } void make_new(T)(size_t n) { auto a = new T[n]; foreach (T i, ref e; a) { e = i; } } This gives me: tmax.d(12): Error: operation not allowed on bool 'i' tmax.d(5): Error: template instance tmax.make_new!(bool) error instantiating As far as I understand, a foreach over an array makes the first value (i) a uint for the index, and the second value (e) a copy of the value in the array (in our case a bool). import std.stdio; void main() { make_new!(bool)(1); } void make_new(T)(size_t n) { auto a = new T[n]; writef("%s\n", typeof(a).stringof); foreach (i,e; a) { writef("%s\n", typeof(i).stringof); writef("%s\n", typeof(e).stringof); } } /* Output: bool[] uint bool */ But to the question about boundaries, 'i' is a uint (size_t), and on a 4GB machine, I can't call "auto a = new bool[size_t.max];". The program segfaults. size_t.max / 2 for a size gives me "Memory allocation failed". size_t.max / 4 works fine. I'm not sure how to get a program to do what you describe.
Mar 09 2011
On 2011-03-09 21:24:57 +0100, Kai Meyer said:I don't see how that works in dmd2, and I don't have much experience with dmd1, so I'll admit that this may be different on dmd1.Derp. I didn't mean bool -- I was talking about byte. (Which should make quite a bit more sense, given that I'm talking about a limit of 256... :D) And, for the record, I'm using DMD 2.052 (OS X). Just replace bool with byte in your program, and it should compile. Sorry for the brain fart ;) -- Magnus Lie Hetland http://hetland.org
Mar 10 2011
Magnus Lie Hetland:Derp. I didn't mean bool -- I was talking about byte. (Which should make quite a bit more sense, given that I'm talking about a limit of 256... :D)Please show a complete minimal program that gives you problem. (I have failed to reproduce your problem on Windows). Bye, bearophile
Mar 10 2011
On Thu, 10 Mar 2011 07:50:21 -0500, bearophile <bearophileHUGS lycos.com> wrote:Magnus Lie Hetland:void main() { auto a = new ubyte[256]; foreach(ubyte i, ref e; a) e = i; } I think you should file this as a bug Magnus, I see no reason why this should result in an infinite loop. Probably the reason is because the compiler rewrites this as: for(ubyte i = 0; i < a.length; i++) where what it should do is: for(size_t _i = 0; _i < a.length; _i++) { auto i = cast(ubyte) _i; ... } or just fail to compile if you use anything that can't hold a size_t as an index type. -SteveDerp. I didn't mean bool -- I was talking about byte. (Which should make quite a bit more sense, given that I'm talking about a limit of 256... :D)Please show a complete minimal program that gives you problem. (I have failed to reproduce your problem on Windows).
Mar 10 2011
Steven Schveighoffer:void main() { auto a = new ubyte[256]; foreach(ubyte i, ref e; a) e = i; }http://d.puremagic.com/issues/show_bug.cgi?id=5725 Bye, bearophile
Mar 10 2011