www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - ranges reading garbage

reply "John Colvin" <john.loughran.colvin gmail.com> writes:
Simplified from something bigger:

import std.range, std.algorithm, std.stdio;

void foo(float[] data, float[] xs, float[] ys)
{
     auto indices = iota(0, data.length, ys.length)
         .map!(xBase =>
                 iota(xBase, xBase + ys.length - 1)
                 .map!(y =>
                     only(y, y+ys.length, y+ys.length+1, y+1))
                 .joiner())
         .joiner();
     writeln(indices);
}

void main()
{
     foo([1,2,3,4,5,6,7,8],
             [0.1,0.2], [10,20,30,40]);
}

prints things like [0, 4, 5, 1, 1, 1459971595, 1459971596, 2, 2, 
1459971596, 1459971597, 3, 4, 8, 9, 5, 5, 4441427819, 4441427820, 
6, 6, 4441427820, 4441427821, 7] but the output isn't consistent, 
the big numbers change on each run.
Feb 15 2015
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
John Colvin:

 prints things like [0, 4, 5, 1, 1, 1459971595, 1459971596, 2, 
 2, 1459971596, 1459971597, 3, 4, 8, 9, 5, 5, 4441427819, 
 4441427820, 6, 6, 4441427820, 4441427821, 7] but the output 
 isn't consistent, the big numbers change on each run.
Try to replace the only() with: [y, y+ys.length, y+ys.length+1, y+1] Like this: import std.range, std.algorithm, std.stdio; void foo(in float[] data, in float[] xs, in float[] ys) safe { iota(0, data.length, ys.length) .map!(xBase => iota(xBase, xBase + ys.length - 1) .map!(y => [y, y+ys.length, y+ys.length+1, y+1]) .joiner) .joiner .writeln; } void main() { foo([1,2,3,4,5,6,7,8], [0.1,0.2], [10,20,30,40]); } In Rust the compiler enforces that all stack-allocated data doesn't come from dead stack frames. In D you have to be careful to avoid doing it. In future this kind of bugs will be hopefully avoided by a better tracking of the memory. I am not sure if http://wiki.dlang.org/DIP69 is able to avoid this bug, if it can't, then DIP69 needs to be improved. Bye, bearophile
Feb 15 2015
next sibling parent reply FG <home fgda.pl> writes:
On 2015-02-15 at 19:43, bearophile wrote:
 void foo(in float[] data, in float[] xs, in float[] ys)  safe {
      iota(0, data.length, ys.length)
      .map!(xBase => iota(xBase, xBase + ys.length - 1)
                     .map!(y => [y, y+ys.length, y+ys.length+1, y+1])
                     .joiner)
      .joiner
      .writeln;
 }

 void main() {
      foo([1,2,3,4,5,6,7,8], [0.1,0.2], [10,20,30,40]);
 }
Odd... Still something is wrong. It prints: [0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 8, 9, 5, 5, 5, 6, 6, 6, 6, 7, 7] instead of this: [0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 8, 9, 5, 5, 9, 10, 6, 6, 10, 11, 7]
Feb 15 2015
parent "bearophile" <bearophileHUGS lycos.com> writes:
FG:

 Odd... Still something is wrong. It prints:
 [0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 8, 9, 5, 5, 5, 6, 6, 6, 
 6, 7, 7]

 instead of this:
 [0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 8, 9, 5, 5, 9, 10, 6, 
 6, 10, 11, 7]
This is less lazy and gives another result: import std.range, std.algorithm, std.stdio; void foo(in float[] data, in float[] xs, in float[] ys) safe { iota(0, data.length, ys.length) .map!(xBase => iota(xBase, xBase + ys.length - 1) .map!(y => [y, y+ys.length, y+ys.length+1, y+1]) .join) .join .writeln; } void main() { foo([1,2,3,4,5,6,7,8], [0.1,0.2], [10,20,30,40]); } What a fun program :-) Bye, bearophile
Feb 15 2015
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Sunday, 15 February 2015 at 18:43:35 UTC, bearophile wrote:
 John Colvin:

 prints things like [0, 4, 5, 1, 1, 1459971595, 1459971596, 2, 
 2, 1459971596, 1459971597, 3, 4, 8, 9, 5, 5, 4441427819, 
 4441427820, 6, 6, 4441427820, 4441427821, 7] but the output 
 isn't consistent, the big numbers change on each run.
Try to replace the only() with: [y, y+ys.length, y+ys.length+1, y+1] Like this: import std.range, std.algorithm, std.stdio; void foo(in float[] data, in float[] xs, in float[] ys) safe { iota(0, data.length, ys.length) .map!(xBase => iota(xBase, xBase + ys.length - 1) .map!(y => [y, y+ys.length, y+ys.length+1, y+1]) .joiner) .joiner .writeln; } void main() { foo([1,2,3,4,5,6,7,8], [0.1,0.2], [10,20,30,40]); } In Rust the compiler enforces that all stack-allocated data doesn't come from dead stack frames. In D you have to be careful to avoid doing it. In future this kind of bugs will be hopefully avoided by a better tracking of the memory. I am not sure if http://wiki.dlang.org/DIP69 is able to avoid this bug, if it can't, then DIP69 needs to be improved. Bye, bearophile
But std.range.OnlyResult!(size_t, 4) is a value type, I don't see where the stack reference is being leaked.
Feb 15 2015
prev sibling parent reply "anonymous" <anonymous example.com> writes:
On Sunday, 15 February 2015 at 18:13:44 UTC, John Colvin wrote:
 Simplified from something bigger:

 import std.range, std.algorithm, std.stdio;

 void foo(float[] data, float[] xs, float[] ys)
 {
     auto indices = iota(0, data.length, ys.length)
         .map!(xBase =>
                 iota(xBase, xBase + ys.length - 1)
                 .map!(y =>
                     only(y, y+ys.length, y+ys.length+1, y+1))
                 .joiner())
         .joiner();
     writeln(indices);
 }

 void main()
 {
     foo([1,2,3,4,5,6,7,8],
             [0.1,0.2], [10,20,30,40]);
 }

 prints things like [0, 4, 5, 1, 1, 1459971595, 1459971596, 2, 
 2, 1459971596, 1459971597, 3, 4, 8, 9, 5, 5, 4441427819, 
 4441427820, 6, 6, 4441427820, 4441427821, 7] but the output 
 isn't consistent, the big numbers change on each run.
Reduced some more: import std.algorithm, std.stdio; void main() { int ys_length = 4; auto indices = [0] .map!(xBase => [0].map!(y => ys_length)) .joiner(); writeln(indices); }
Feb 15 2015
parent reply "anonymous" <anonymous example.com> writes:
On Sunday, 15 February 2015 at 19:54:45 UTC, anonymous wrote:
 Reduced some more:

 import std.algorithm, std.stdio;
 void main()
 {
     int ys_length = 4;
     auto indices = [0]
         .map!(xBase => [0].map!(y => ys_length))
         .joiner();
     writeln(indices);
 }
And more: import std.stdio; struct MapResult(alias fun) { property int front() {return fun();} property auto save() {return typeof(this)();} } void main() { int ys_length = 4; auto dg = {return MapResult!({return ys_length;})();}; writeln(dg().front); /* 4, correct */ writeln(dg().save.front); /* garbage */ }
Feb 15 2015
parent "anonymous" <anonymous example.com> writes:
On Sunday, 15 February 2015 at 22:38:20 UTC, anonymous wrote:
 And more:

 import std.stdio;
 struct MapResult(alias fun)
 {
      property int front() {return fun();}
      property auto save() {return typeof(this)();}
 }
 void main()
 {
     int ys_length = 4;
     auto dg = {return MapResult!({return ys_length;})();};
     writeln(dg().front); /* 4, correct */
     writeln(dg().save.front); /* garbage */
 }
It's already in bugzilla: https://issues.dlang.org/show_bug.cgi?id=9685
Feb 16 2015