Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
February 15, 2015 ranges reading garbage | ||||
---|---|---|---|---|
| ||||
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. |
February 15, 2015 Re: ranges reading garbage | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | 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 |
February 15, 2015 Re: ranges reading garbage | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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]
|
February 15, 2015 Re: ranges reading garbage | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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.
|
February 15, 2015 Re: ranges reading garbage | ||||
---|---|---|---|---|
| ||||
Posted in reply to FG | 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
|
February 15, 2015 Re: ranges reading garbage | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | 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);
}
|
February 15, 2015 Re: ranges reading garbage | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | 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 */
}
|
February 16, 2015 Re: ranges reading garbage | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | 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 |
Copyright © 1999-2021 by the D Language Foundation