Access violation using chain()
Brad Anderson
eco at gnuk.net
Sun Apr 22 02:20:08 PDT 2012
On Thursday, 19 April 2012 at 16:19:05 UTC, Brad Anderson wrote:
> On Thu, Apr 19, 2012 at 7:25 AM, Christophe
> <travert at phare.normalesup.org>wrote:
>
>> "Brad Anderson" , dans le message (digitalmars.D.learn:34902),
>> a écrit :
>> > Perhaps I'm just misunderstanding something about closures
>> > but
>> > the following code seems to behave oddly:
>> >
>> > import std.stdio, std.range, std.algorithm, std.string;
>> >
>> > void main()
>> > {
>> > auto lst = ["a", "b"];
>> > auto rng = range_gen(lst);
>> > writeln(rng.take(5));
>> > }
>> > auto range_gen(string[] lst)
>> > {
>> > auto a = sequence!"n+1"().map!(a=>format("%s%d",
>> > lst[0],
>> > a))();
>> > return chain(lst, a); // access violation
>> > //return a; // works
>> > }
>>
>> My guess is that chain takes lst by reference, just like the
>> delegates
>> for map, wo both are working on the same slice instance. The
>> chain first
>> pops elements from lst, and then calls the mapped sequence. At
>> that
>> time, lst is empty.
>>
>> You can just copy lst before you give it to chain (or to map's
>> delegate)
>> to solve this bug:
>>
>> auto range_gen(string[] lst)
>> {
>> auto a = sequence!"n+1"().map!(a=>format("%s%d", lst[0],
>> a))();
>> string[] lst2 = lst;
>> return chain(lst2, a); // access violation
>> }
>>
>>
> Ah, that would make sense. I'll test and make sure when I get
> home. Range
> consumption tricks me more often than I wish. I'll eventually
> learn to
> look out for it more actively.
>
> Regards,
> Brad Anderson
Ok, so this wasn't the problem. I have no idea what the problem
is. Using string[] lst = list; doesn't help nor does lst.save.
I can get some really weird behavior messing around with this.
Access violations that appear or disappear when symbolic debug
info is enabled. Here's an example of a weird one:
import std.stdio, std.range, std.algorithm, std.string;
void main()
{
writeln(gen(["a", "b"]).take(5));
}
auto gen(string[] lst)
{
auto prefix = lst[0];
auto a = iota(10).map!(a=>format("%s%d", prefix, a))();
//auto a = sequence!"n+1"().map!(a=>format("%s%d",
prefix, a))();
return chain(lst.save, a);
}
Compiling that using DMD 2.059 without -g results in a UTF
exception (memory corruption?) after outputting ["a", "b",.
Compiling with -g produces no exception but the output is
incorrect (["a", "b", "0", "1", "2"] should be ["a", "b", "a0",
"a1", "a2"]). Now, if you replace the iota line with with the
commented out sequence line it works the other way. Without -g
gives no exception (but correct output this time), with -g
results in a UTF exception. It's a bit unsettling that adding
debug info can change the behavior of the program.
I suppose this makes this a bug but I'm not sure what I'd call
it. Is it a bug with chain() or with closures? Is the symbolic
debug information differences a different bug?
Regards,
Brad Anderson
More information about the Digitalmars-d-learn
mailing list