Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is GC.KeepAlive required here, or can I rely on locals and arguments keeping an object alive?

I have a bunch of methods that take the WPF's WriteableBitmap and read from its BackBuffer directly, using unsafe code.

It's not entirely clear whether I should use GC.KeepAlive whenever I do something like this:

int MyMethod(WriteableBitmap bmp)
{
    return DoUnsafeWork(bmp.BackBuffer);
}

On the one hand, there remains a reference to bmp on MyMethod's stack. On the other, it seems like relying on implementation detail - this could compile to a tail call, for example, keeping no reference to bmp the moment DoUnsafeWork is entered.

Similarly, imagine the following hypothetical code:

int MyMethod()
{
    WriteableBitmap bmp1 = getABitmap();
    var ptr = bmp.BackBuffer;
    WriteableBitmap bmp2 = getABitmap();
    return DoUnsafeWork(ptr, bmp2);
}

In theory, a reference to bmp1 remains on the stack until the method returns, but again, it seems like using an implementation detail. Surely the compiler is free to merge bmp1 and bmp2 because they're never live at the same time, and even if the compiler never does that surely the JITter still can, and probably does (e.g. by storing them both in the same register, first one, then the other).

So, in general: should I rely on locals/arguments being valid references to an object, or should I always use GC.KeepAlive to guarantee correctness?

This is especially puzzling since, apparently, FxCop thinks GC.KeepAlive is always bad.

like image 656
Roman Starkov Avatar asked Jan 03 '12 14:01

Roman Starkov


1 Answers

Should I rely on locals/arguments being valid references to an object?

No. Your analysis is correct; the jitter is entirely within its rights to tell the garbage collector that the contents of the local are dead the moment they are no longer in use by managed code.

should I always use GC.KeepAlive to guarantee correctness?

Yes. That's what it's for.

like image 167
Eric Lippert Avatar answered Nov 03 '22 00:11

Eric Lippert