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

Nicolas Sicard dransic at gmail.com
Mon Jan 27 12:03:38 PST 2014


On Monday, 27 January 2014 at 14:47:21 UTC, Steven Schveighoffer 
wrote:
> 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

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

Nicolas


More information about the Digitalmars-d-learn mailing list