Is this a bug or feature?

Kirk McDonald kirklin.mcdonald at gmail.com
Tue Jan 16 02:30:40 PST 2007


Li Jie wrote:
> Code:
> 
> # import std.gc;
> #
> # class Foo{
> #   private:
> #   int value = 3;
> #
> #   public:
> #   ~this(){
> #       writefln("call destructor");
> #   }
> #
> #   void delegate() foo(){
> #       return delegate void(){
> #           writefln(value);
> #       };
> #   }
> # }
> #
> # void main(){
> #   void delegate() dg = (new Foo).foo;
> #   std.gc.fullCollect();
> #   dg();
> # }
> 
> I expect it output "3", but the output is a big number, not "3".
> 
> If comment std.gc.fullCollect(), it output "3", and it is right.
> 
> I think a closure must save all contexts, isn't it?

D does not have true closures. If the stack frame of the enclosing 
function is invalidated, then all bets are off.

In Foo.foo above, the 'value' variable is a member of the 'this' 
reference. When Foo.foo returns, that delegate literal's context pointer 
is invalidated, and (therefore) so is the 'this' reference.

If you want a delegate with a more persistent context, you must use a 
delegate to a member function, as in:

class Foo {
     int value = 3;
     ~this() { writefln("dtor"); }
     void foo() {
         writefln(value);
     }
}

void main() {
     // Note the '&'
     void delegate() dg = &(new Foo).foo;
     std.gc.fullCollect();
     dg();
}

-- 
Kirk McDonald
Pyd: Wrapping Python with D
http://pyd.dsource.org


More information about the Digitalmars-d-learn mailing list