View mode: basic / threaded / horizontal-split · Log in · Help
March 08, 2005
anonymous delegates in objects. bug?
This code works:

<code>
import std.stdio;

void delegate () dg;

class A
{
	this() { dg = delegate void () { foo(); }; }
	void foo() { writefln("foo"); }
}

void main()
{
	B b = new B();
	A a = new A();

	dg(); // prints "foo"
}
</code>

But this code throws AV:

<code>
import std.stdio;

class B { void delegate () dg; }

B b;

class A
{
	this() { b.dg = delegate void () { foo(); }; }
	void foo() { writefln("foo"); }
}

void main()
{
	B b = new B();
	A a = new A();

	b.dg(); // AV here
}
</code>

Whats the difference? Is it a bug or specific D behaviour?
March 08, 2005
Re: anonymous delegates in objects. bug?
Ilya Zaitseff wrote:
> This code works:
> 
> <code>
> import std.stdio;
> 
> void delegate () dg;
> 
> class A
> {
>     this() { dg = delegate void () { foo(); }; }
>     void foo() { writefln("foo"); }
> }
> 
> void main()
> {
>     B b = new B();
>     A a = new A();
> 
>     dg(); // prints "foo"
> }
> </code>
> 
> But this code throws AV:
> 
> <code>
> import std.stdio;
> 
> class B { void delegate () dg; }
> 
> B b;
> 
> class A
> {
>     this() { b.dg = delegate void () { foo(); }; }
>     void foo() { writefln("foo"); }
> }
> 
> void main()
> {
>     B b = new B();
>     A a = new A();
> 
>     b.dg(); // AV here
> }
> </code>
> 
> Whats the difference? Is it a bug or specific D behaviour?

You made a mistake - A.this() sets the global b, while "B b=new B()" 
creates the local b.. When you execute b.dg(), it's not the global b, so 
it doesn't have the delegate set, hence AV.. In fact, I'd say that it's 
A.this() that produces AV, because the global b is null...


xs0
March 08, 2005
Re: anonymous delegates in objects. bug?
On Tue, 08 Mar 2005 18:07:00 +0100, xs0 <xs0@xs0.com> wrote:

> Ilya Zaitseff wrote:
>>  Whats the difference? Is it a bug or specific D behaviour?
>
> You made a mistake - A.this() sets the global b, while "B b=new B()"  
> creates the local b.. When you execute b.dg(), it's not the global b, so  
> it doesn't have the delegate set, hence AV.. In fact, I'd say that it's  
> A.this() that produces AV, because the global b is null...
>
> xs0

Oops, just a stupid typo :)

Actually second code snippet is:

<code>
import std.stdio;

class B
{
  void delegate () dg;
  void run() { dg(); }
}

B b;

class A
{
  this() { b.dg = delegate void () { foo(); }; }
  void foo() { writefln("foo"); }
}

void main()
{
  b = new B();
  A a = new A();
  b.dg(); // prints "foo"
  b.run(); // AV here
}
</code>

bug, isn't it?
March 09, 2005
Re: anonymous delegates in objects. bug?
Ilya Zaitseff wrote:
> <code>
> import std.stdio;
> 
> class B
> {
>   void delegate () dg;
>   void run() { dg(); }
> }
> 
> B b;
> 
> class A
> {
>   this() { b.dg = delegate void () { foo(); }; }
>   void foo() { writefln("foo"); }
> }
> 
> void main()
> {
>   b = new B();
>   A a = new A();
>   b.dg(); // prints "foo"
>   b.run(); // AV here
> }
> </code>
> 
> bug, isn't it?

My guess is that the problem is that the delegate you're creating is a 
stack delegate, and the stack frame is no longer valid.  Remembery that 
the line
	foo();
in the delegate literal is really
	this.foo();
and that, since this is a stack delegate, the compiler is gettting 
'this' from a function argument which was on the stack; thus, the 
statement really becomes
	stack_frame.this.foo();
where stack_frame is the pointer which is saved in the delegate.  This 
pointer is created when the delegate literal is created, and is invalid 
from the moment that the stack frame (the constructor) exits.

This code should work fine if you change A's constructor to this:
	this() { b.dg = &this.foo; }
March 10, 2005
Re: anonymous delegates in objects. bug?
On Wed, 09 Mar 2005 11:09:01 -0700, Russ Lewis  
<spamhole-2001-07-16@deming-os.org> wrote:

> Ilya Zaitseff wrote:
>> <code>
>> import std.stdio;
>>  class B
>> {
>>   void delegate () dg;
>>   void run() { dg(); }
>> }
>>  B b;
>>  class A
>> {
>>   this() { b.dg = delegate void () { foo(); }; }
>>   void foo() { writefln("foo"); }
>> }
>>  void main()
>> {
>>   b = new B();
>>   A a = new A();
>>   b.dg(); // prints "foo"
>>   b.run(); // AV here
>> }
>> </code>
>>  bug, isn't it?
>
> My guess is that the problem is that the delegate you're creating is a  
> stack delegate, and the stack frame is no longer valid.  Remembery that  
> the line
> 	foo();
> in the delegate literal is really
> 	this.foo();
> and that, since this is a stack delegate, the compiler is gettting  
> 'this' from a function argument which was on the stack; thus, the  
> statement really becomes
> 	stack_frame.this.foo();
> where stack_frame is the pointer which is saved in the delegate.  This  
> pointer is created when the delegate literal is created, and is invalid  
> from the moment that the stack frame (the constructor) exits.
>
> This code should work fine if you change A's constructor to this:
> 	this() { b.dg = &this.foo; }

I got it. Thanks.
Top | Discussion index | About this forum | D home