On Monday, 27 January 2014 at 14:47:21 UTC, Steven Schveighoffer wrote:
On Mon, 27 Jan 2014 03:17:51 -0500, Nicolas Sicard <dran...@gmail.com> wrote:

Actually I used a struct because the code is more complex, and it builds an array of delegates, which are returned from global functions, like:
---
struct Transformer
{
        real delegate(real)[] funs;

        addFun(real x)
        {
                fun ~= makeFun(x);
        }

        // etc.
}

real delegate(real) makeFun(real x)
{
        return (real r) => r * x;
}
---

This means my design was bad in the first place.
Thanks for the explanation.

Actually, the delegate there is fine! The makeFun function becomes a closure, and will be allocated on the heap.

Where you are running into trouble is simply that the struct goes out of scope, and the array is therefore invalid.

In fact, I think you were already doing that before (creating a closure).

Here is a possible solution to your original example:

        auto applyTo(T)(T list)
        {
                import std.algorithm;
                auto funcopy = fun;
                return list.map!(x => funcopy(x));
        }

What's happening here is that funcopy is a stack local variable. However, since you're creating a delegate that uses local variables, the compiler creates a closure. In essence, it's like putting a new struct on the heap with the single member funcopy, and using that as the context pointer. Note that the original code also creates a closure, but 'fun' is a member of the hidden 'this' reference. Because the 'this' reference refers to destructed data, fun is garbage, hence the segfault.

I actually was wrong about my original diagnosis. The delegate stored in your original code does NOT store a delegate with a context pointer that points to 'this', it's pointing to a closure. Because 'x' doesn't exist inside the struct, only inside the function. But my statements were still good advice, don't store pointers to yourself inside a struct :)

-Steve

This makes perfect sense. My real code works as expected now.
Thanks for the clear explanation, and advice.

Nicolas

Reply via email to