On Sat, Dec 07, 2013 at 07:32:46PM +0100, Johannes Pfau wrote: > Am Sat, 7 Dec 2013 08:43:53 -0800 > schrieb "H. S. Teoh" <hst...@quickfur.ath.cx>: > > > On Sat, Dec 07, 2013 at 10:08:25AM +0100, Johannes Pfau wrote: > > [...] > > > It looks like we actually generate a closure here which contains > > > the this pointer instead of directly using the struct as a context > > > pointer. That is probably an optimization bug in dmd, but it > > > doesn't matter in this case as the problem would exist for > > > closures and normal delegates. > > > > The problem is that delegates are never passed the this pointer from > > the caller; it is assumed that it's part of their context. You never > > write `myStruct.dg(args)`, but simply `dg(args)`. But by the time > > the delegate is invoked, you can't guarantee that `this` is still > > valid. Only the caller knows what copy of the struct it still > > holds, but this isn't communicated to the delegate. (On second > > thought, even if it *did* pass the updated `this` to the delegate, > > it would still be wrong, because there could be multiple copies of > > the struct by then, and who knows which copy the delegate was > > supposed to be operating on?) > > True, but that's not what I meant ;-) > I always get the terminology related to closures wrong so sorry if > that didn't make sense. > > What I meant is this: In the first example I posted, > http://dpaste.dzfl.pl/433c0a3d > the delegate does not access _function variables_. It only accesses > the this pointer. So there's no need for it to be a real closure and > allocate memory, it could instead be a normal delegate with the > context pointer simply set to the this pointer at the moment the > delegate is created.
The problem is that when `this` is closed over, it's one thing, but when the delegate is invoked later, `this` may no longer be valid. For example: struct S { int x = 123; // canary void delegate() getDelegate() { // Closes over `this` return () => x; } } void delegate() dg; S makeStruct() { S s; dg = s.getDelegate(); return s; } void main() { auto s = makeStruct(); dg(); // <-- NG } T -- Indifference will certainly be the downfall of mankind, but who cares? -- Miquel van Smoorenburg