Nasty corner case behaviour

Meta jared771 at gmail.com
Fri Apr 19 23:42:53 UTC 2019


On Thursday, 18 April 2019 at 05:01:17 UTC, H. S. Teoh wrote:
> Got bitten by this today:
>
> 	import std.algorithm : filter, map;
> 	import std.stdio;
>
> 	struct S {
> 		bool flag;
> 		auto method() {
> 			return [ 1 ].filter!(e => flag);
> 		}
> 	}
>
> 	void main() {
> 		auto s = S(true);
> 		writeln(s.method);
>
> 		auto arr = [ s ];
> 		writeln(arr[0].method);
>
> 		auto mappedArray = arr.map!(e => e.method);
> 		writeln(mappedArray.front);
> 		writeln(mappedArray);
> 	}
>
> Expected output:
>
> 	[1]
> 	[1]
> 	[1]
> 	[[1]]
>
> Actual output:
>
> 	[1]
> 	[1]
> 	[1]
> 	[[]]
>
> Exercise for the reader: explain the problem.
>
> Hint: it's not a bug in Phobos.
>
> If method() is changed to the following, the problem goes away:
>
> 	auto method() {
> 		auto _flag = flag;
> 		return [ 1 ].filter!(e => _flag);
> 	}
>
> It should be obvious by now that the problem is caused by the 
> lambda incorrectly closing over a member variable in a struct 
> instance that subsequently goes out of scope, while the 
> returned closure lives on. Unfortunately, neither -dip25 nor 
> -dip1000 catches this leakage, even if main() is marked @safe.
>
>
> T

I find this one a bit confusing. Shouldn't the struct be moved to 
the heap when the compiler detects that it's being closed over?


More information about the Digitalmars-d mailing list