Using a delegate stored as a member of a destroyed struct?

Steven Schveighoffer schveiguy at yahoo.com
Mon Jan 27 06:47:21 PST 2014


On Mon, 27 Jan 2014 03:17:51 -0500, Nicolas Sicard <dransic at 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


More information about the Digitalmars-d-learn mailing list