这里需要GC.KeepAlive,或者我可以依靠当地人和参数保持对象还活着吗?当地、对象、参数、GC

2023-09-04 07:24:27 作者:见妓行事

我有一大堆的方法,即把WPF的 WriteableBitmap的并从其后备缓冲读直接使用不安全$ C $℃。

这不是完全清楚,我是否应该使用 GC.KeepAlive 每当我做这样的事情:

  INT的MyMethod(WriteableBitmap的BMP)
{
    返回DoUnsafeWork(bmp.BackBuffer);
}
 

在一方面,仍然存在对的MyMethod 的堆栈引用 BMP 。另一方面,它似乎是依靠实现的细节 - 这可能编译成尾调用,例如,保持没有提及 BMP 的时刻 DoUnsafeWork 输入。

同样,想象下面的假设code:

  INT的MyMethod()
{
    WriteableBitmap的BMP1 = getABitmap();
    VAR PTR = bmp.BackBuffer;
    WriteableBitmap的BMP2 = getABitmap();
    返回DoUnsafeWork(PTR,BMP2);
}
 

在理论上,引用 BMP1 保持堆栈,直到方法返回的,但是,它似乎像使用一个实现细节。当然,编译器可以自由合并 BMP1 BMP2 ,因为他们永远生活在同一时间,即使编译器从来不会说肯定抖动还算可以,而且很可能不会(在同一个寄存器,第一个,那么其他存储他们两个EG)。

所以,总的来说:我应该依靠当地人/参数是一个对象的有效引用,或者我应该始终使用 GC.KeepAlive 来保证正确性。 街访 金村人靠什么过冬

这是特别是因为百思不得其解,显然,FxCop认为GC.KeepAlive总是不好。

解决方案   

我应该依靠当地人/参数是一个对象有效的参考?

没有。你的分析是正确的;抖动是完全在它告诉本地的内容都死了,他们不再由管理code使用的那一刻垃圾收集器的权利。

  

我应该始终使用GC.KeepAlive来保证正确性?

是的。这就是它了。

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.