Thread overview
delegates and temporary struct
May 16, 2013
Jack Applegame
May 17, 2013
Maxim Fomin
May 17, 2013
1100110
May 16, 2013
Look at this code:
>import std.stdio;
>
>class Foo {
>  int value = 123456;
>}
>
>struct Bar {
>  this(Foo f) { foo = f; }
>  @property auto lambda() {
>    return (){ writefln("value = %s", foo.value); };
>  }
>  Foo foo;
>}
>auto getLambda(Foo f) {
>  return Bar(f).lambda; // lambda closure points to temporary Bar on the stack
>}
>void main() {
>  Foo foo = new Foo;
>  auto lambda = getLambda(foo);
>  lambda(); // undefined behaviour? prints some number, but not 123456
>}
It compiles, but result is unpredictable.

Platform: Windows 7, dmd 2.062

For reproducing this behaviour it's necessary to omit -inline and -O flags, try simple "rdmd test.d"
May 17, 2013
On Thursday, 16 May 2013 at 22:53:56 UTC, Jack Applegame wrote:
> Look at this code:
>>import std.stdio;
>>
>>class Foo {
>> int value = 123456;
>>}
>>
>>struct Bar {
>> this(Foo f) { foo = f; }
>> @property auto lambda() {
>>   return (){ writefln("value = %s", foo.value); };
>> }
>> Foo foo;
>>}
>>auto getLambda(Foo f) {
>> return Bar(f).lambda; // lambda closure points to temporary Bar on the stack
>>}
>>void main() {
>> Foo foo = new Foo;
>> auto lambda = getLambda(foo);
>> lambda(); // undefined behaviour? prints some number, but not 123456
>>}
> It compiles, but result is unpredictable.
>
> Platform: Windows 7, dmd 2.062
>
> For reproducing this behaviour it's necessary to omit -inline and -O flags, try simple "rdmd test.d"

http://d.puremagic.com/issues/show_bug.cgi?id=9352
May 17, 2013
On 05/16/2013 09:21 PM, Maxim Fomin wrote:
> On Thursday, 16 May 2013 at 22:53:56 UTC, Jack Applegame wrote:
>> Look at this code:
>>> import std.stdio;
>>>
>>> class Foo {
>>> int value = 123456;
>>> }
>>>
>>> struct Bar {
>>> this(Foo f) { foo = f; }
>>> @property auto lambda() {
>>>   return (){ writefln("value = %s", foo.value); };
>>> }
>>> Foo foo;
>>> }
>>> auto getLambda(Foo f) {
>>> return Bar(f).lambda; // lambda closure points to temporary Bar on
>>> the stack
>>> }
>>> void main() {
>>> Foo foo = new Foo;
>>> auto lambda = getLambda(foo);
>>> lambda(); // undefined behaviour? prints some number, but not 123456
>>> }
>> It compiles, but result is unpredictable.
>>
>> Platform: Windows 7, dmd 2.062
>>
>> For reproducing this behaviour it's necessary to omit -inline and -O flags, try simple "rdmd test.d"
> 
> http://d.puremagic.com/issues/show_bug.cgi?id=9352

I get an incorrect but consistent number using dmd -m32 test.d and the correct number using dmd -m64 test.d on Linux.



May 17, 2013
On Thu, 16 May 2013 18:53:55 -0400, Jack Applegame <japplegame@gmail.com> wrote:

> Look at this code:
>> import std.stdio;
>>
>> class Foo {
>>  int value = 123456;
>> }
>>
>> struct Bar {
>>  this(Foo f) { foo = f; }
>>  @property auto lambda() {
>>    return (){ writefln("value = %s", foo.value); };
>>  }
>>  Foo foo;
>> }
>> auto getLambda(Foo f) {
>>  return Bar(f).lambda; // lambda closure points to temporary Bar on the stack
>> }
>> void main() {
>>  Foo foo = new Foo;
>>  auto lambda = getLambda(foo);
>>  lambda(); // undefined behaviour? prints some number, but not 123456
>> }
> It compiles, but result is unpredictable.
>
> Platform: Windows 7, dmd 2.062
>
> For reproducing this behaviour it's necessary to omit -inline and -O flags, try simple "rdmd test.d"

Using struct delegates is VERY frought with danger.  You must ensure the struct is alive when the delegate is called.  I don't think the compiler can detect the cases where it's not and allocate a closure.

I also have found this out the hard way...

Only recourse is to ensure the struct is on the heap.

-Steve