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

人走茶凉 提交于 2019-12-23 07:12:03

问题


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.


回答1:


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.




回答2:


If you have called WriteableBitmap.Lock before getting the back buffer then the WriteableBitmap should be pinned and underlying memory will not be moved. At least that's my interpretation of the WriteableBitmapAPI.

I have used WriteableBitmap extensively, in particular the open source WriteableBitmapEx library on codeplex (disclosure, I have contributed once to this library but its not my project). This uses the pattern of Lock / Access Backbuffer (repeatedly) / unlock / Invalidate to draw. I've never had a problem with this pattern even though the backbuffer IntPtr is stored in a struct and passed around the application.

Best regards,



来源:https://stackoverflow.com/questions/8713779/is-gc-keepalive-required-here-or-can-i-rely-on-locals-and-arguments-keeping-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!