我们正在处理 .Net 程序中 GC 太快的问题。 因为我们使用的是带有原生资源的类,并且没有调用GC.KeepAlive(),所以GC会在Native访问结束之前收集对象。结果程序崩溃了。 我们遇到的问题正是如下所述:
Does the .NET garbage collector perform predictive analysis of code?
像这样:
{ var img = new ImageWithNativePtr();
IntPtr p = img.GetData();
// DANGER!
ProcessData(p);
}
要点是:JIT 生成的信息向 GC 显示在 GetData() 运行时未使用 img。如果 GC 线程在正确的时间出现,它会收集 img,然后程序就会崩溃。可以通过附加 GC.KeepAlive(img); 来解决这个问题 不幸的是,已经编写了太多代码(在太多地方)来轻松纠正问题。
因此:是否有一个属性(即 ImageWithNativePtr)可以使 JIT 的行为类似于调试版本?在调试版本中,变量 img 将保持有效,直到作用域结束 ( } ),而在发布版本中,它会在注释 DANGER 处失去有效性。
最佳答案
据我所知,没有办法根据方法引用的类型来控制抖动的行为。您也许可以归因于该方法本身,但这不会满足您的订单。既然如此,你就应该硬着头皮重写代码。 GC.KeepAlive 是一种选择。另一种方法是让 GetData
返回一个安全句柄,其中包含对该对象的引用,并让 ProcessData
接受该句柄而不是 IntPtr
— 这就是无论如何,这是一个很好的做法。然后,GC 将保留安全句柄,直到方法返回。如果您的大部分代码都使用 var
而不是代码片段中的 IntPtr
,您甚至可能无需修改每个方法即可逃脱。
关于c# - 如何使 JIT 将堆栈变量扩展到范围末尾(GC 太快),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6898336/