考虑以下C ++ / CLI代码片段:
public ref class MyData
{
private:
UnmanagedObject* pobj;
public:
MyData()
{
pobj = ... // acquire unmanaged pointer
}
!MyData()
{
delete pobj; // finalizer
pobj = NULL;
}
void DoSomething()
{
// next line calls a native method that has no knowledge of .NET
CallToNativeMethod(data->pobj);
}
static void Test()
{
MyData^ data = gcnew MyData();
data->DoSomething()
}
}
此类表示某些非托管API的.NET包装器。在我的项目中,我目前正在处理一个难以追踪的错误 - 似乎MyData
的实例在方法DoSomething()
仍在执行时被垃圾收集。以下是我认为发生的事情:
Test()
,创建MyData
DoSomething()
称为DoSomething()
调用本机方法MyData
的实例并调用终结器pobj
,它由仍在执行的本机方法使用 我的两个问题:
编辑(一些其他信息):代码崩溃,AccessViolationException
从本机方法冒出来,可以被try..catch
Test()
抓住}。为了进行调试,我插入了几个日志记录调用,它们显示了以下执行顺序:
答案 0 :(得分:0)
您应该将GC::KeepAlive(data)添加到Test()方法的底部。
请注意,如果CallToNativeMethod调用另一个线程并立即返回,则托管数据对象和GC引用将很快超出范围,然后再次被垃圾回收。在这种情况下,您需要创建一种调用KeepAlive的通知代码,直到它获得信号。