Consider:
import std.stdio;
void main() {
void delegate()[] a;
foreach (i; 1 .. 10) {
a ~= { writeln(i); };
}
foreach (f; a) {
f();
}
}
This program prints an arbitrary value every run, which means i is not properly closed upon.
Comment #1 by entheh — 2012-09-17T17:09:04Z
Here's more code which I think exhibits the same bug, and also demonstrates some workarounds and some more info on the nature of the bug.
This code breaks with 2.060 on Windows, compiling with no switches at all, just "dmd filename.d". The production code I derived it from was fine on 2.059.
------------
import std.stdio;
void main() {
broken();
reffix();
noclosefix();
}
void broken() {
foreach (z; 0..1) {
writeln(z); //Corrupt
() {writeln(z);} (); //Corrupt (same value)
}
}
//The above demonstrates that the variable is broken both inside and outside the closure.
//Adding 'ref' fixes it:
void reffix() {
foreach (ref z; 0..1) {
writeln(z); //0
() {writeln(z);} (); //0
}
}
//It only breaks if 'z' is closed into the lambda:
void noclosefix() {
foreach (z; 0..1) {
writeln(z); //0
int z2=z;
() {writeln(z2);} (); //0
}
}
------------
The sort of corrupt values I see for z are for example
28835840 = 0x01B80000
29949952 = 0x01C90000
38535168 = 0x024C0000
36110336 = 0x02270000
But it's always the same between one writeln and the other.
Also breaks with foreach_reverse.
Comment #2 by hsteoh — 2014-09-24T20:28:05Z
Still happens on git HEAD (v2.067-devel-cfe52d3).
Comment #3 by k.hara.pg — 2014-10-02T05:45:34Z
*** This issue has been marked as a duplicate of issue 2043 ***
Comment #4 by entheh — 2014-10-02T09:49:49Z
Not a duplicate.
The present bug talks about corrupt values coming out of thin air. I quote myself:
"The sort of corrupt values I see for z are for example
28835840 = 0x01B80000
29949952 = 0x01C90000
38535168 = 0x024C0000
36110336 = 0x02270000
But it's always the same between one writeln and the other."
This is not happening at all in the other bug. The other bug is more like the well-known C# foreach lambda problem, but on steroids.
Comment #5 by gabor.mezo — 2014-10-02T12:05:15Z
I can confirm that this issue is NOT present on DMD 2.066.0 Windows.
Comment #6 by entheh — 2014-10-02T12:09:35Z
Great - I haven't retested recently. Feel free to resolve :)
Comment #7 by gabor.mezo — 2014-10-02T12:15:28Z
We have "Still happens on git HEAD (v2.067-devel-cfe52d3)" comment above. Maybe it only appears on Linux, or reappeared in v2.067. Worth a check before goes resolved.
Comment #8 by entheh — 2014-10-02T12:24:37Z
True, I forgot that was there. For what it's worth, I originally encountered the bug on Windows.
Comment #9 by ketmar — 2014-10-02T12:54:07Z
just checked with HEAD-1d1998 on 32-bit GNU/Linux. first sample prints alot of '9', second sample prints alot of '0'. so it works at least for 32-bits. maybe this is 64-bit issue?
Comment #10 by entheh — 2014-10-02T13:00:03Z
I think I was working in 32-bit though.
hsteoh, can you tell us more about the situation you reproduced it in?
Comment #11 by hsteoh — 2014-10-02T15:58:14Z
Just retested it on Linux/64 (git HEAD), seems that garbage values are no longer happening. It still shows improper/missing closure over i, though, because the output is all 9's, meaning that it's closing on a single variable i shared across all iterations, as opposed to unique values per iteration.
So basically the only bug left is issue #2043; the corrupted values Andrei reported seem to have been fixed since.
Comment #12 by robert.schadek — 2024-12-13T18:01:13Z