Thread overview | ||||||
---|---|---|---|---|---|---|
|
May 16, 2013 delegates and temporary struct | ||||
---|---|---|---|---|
| ||||
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 Re: delegates and temporary struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Applegame | 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 Re: delegates and temporary struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin Attachments:
| 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 Re: delegates and temporary struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Applegame | 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
|
Copyright © 1999-2021 by the D Language Foundation