Gil*_*lad 2 c# garbage-collection defragmentation
我正在编写一个程序,在多个线程中调用多个基于C的函数(p/Invoke).
程序有时会因访问冲突错误而崩溃.我的第一个想法是GC优化了内存,并将C函数正在处理的内存块移动到另一个位置.
我想做的是让GC工作,但禁用它移动(defrags)内存的部分.
有没有办法做到这一点?
正如其他答案所说,首先要做的是确保正确固定对象.假设你已经这样做了,还有什么可能出错?
class C
{
public int handle;
...
~C() { InteropLibrary.DestroyHandle(handle); }
}
void M()
{
C c = GetSomeObjectUsefulInUnmanagedCode();
D d = InteropLibrary.UnmanagedMethodThatUsesHandle(c);
// COMMENT
d.DoSomethingWithStoredHandle();
}
Run Code Online (Sandbox Code Playgroud)
如果垃圾收集发生在COMMENT(*)怎么办?垃圾收集器可以自由地说"嘿,c在这种方法中,局部变量永远不会被再次引用;我可以积极地将它视为死!".如果终结器运行并且句柄被销毁,那么当最后一个方法运行时,它将访问被销毁的句柄并崩溃.
要解决这个罕见但可能出现的问题,您可以使用它GC.KeepAlive来告诉垃圾收集器在清理特定引用时不那么积极.如果你保持c活着直到方法结束,那么你知道它的析构函数不可能运行.
(*)当然GC运行在不同的线程上,并且可以随时运行.GC操作和不可中断的操作的详细信息很复杂,您不应该依赖这些实现细节来确保正确性.