假设您有一个托管类,它将委托成员转换为本机函数指针并将其交给本机代码。假设类/委托保留在范围内,并且在本机代码的生命周期内不会更改(因此GC不会明显破坏它)。在这种情况下应该注意哪些其他问题?例如,GC是否可以移动委托或委托引用的实际方法,并使您的本机代码具有访问冲突?
答案 0 :(得分:2)
我不是一个.Net专家,但我认为你应该看看这里:Marshal Callbacks and Delegates Using C++ Interop。
请注意,这是可能的,但不是 必要的,用来固定代表 pin_ptr以防止它被发现 重新定位或处置 垃圾收集器。保护 过早的垃圾收集是 需要,但钉扎提供更多 保护不是必要的,因为它 防止收集,但也防止 重新定位。
答案 1 :(得分:2)
GC可以移动委托,但不能移动委托包装的本机代码。因此,只要未收集委托,函数指针就会保持有效。
请注意,“在范围内”不足以阻止收集对象。必须使用它(可能通过调用GC.KeepAlive
)。
答案 2 :(得分:2)
快速搜索会在问题上显示一些Microsoft guidance。本文适用于托管C ++,但该指南应适用于CLR上的任何语言。
这个想法是你需要阻止代理本身被重新定位或处理,但(自然地)底层代码不能移动。一旦JIT编译为本机代码,代码就会被修复并且不应该移动。
答案 3 :(得分:2)
似乎可以固定委托/函数的内存位置,但这会阻碍.NET GC的主要优势:压缩。
完成GC扫描后,每个对象都将重新定位到内存中以保持连续。这使得访问和分配的速度都快于堆碎片时的速度。如果你必须在堆中固定一个对象,GC就必须解决它,如果多次完成,可能会导致一些非常重要的堆碎片。 (顺便说一句,这是由Ron Warholic链接的文章中的GCHandle解决的。我不确定这是否可以在托管C ++之外使用。)