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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With