gpt4 book ai didi

c# - C++/命令行界面 : preventing garbage collection on managed wrapper of unmanaged resource

转载 作者:可可西里 更新时间:2023-11-01 08:25:19 25 4
gpt4 key购买 nike

我有一个 C++ 非托管类 NativeDog 需要从 C# 使用,所以我创建了一个包装类 ManagedDog

// unmanaged C++ class
class NativeDog
{
NativeDog(...); // constructor
~NativeDog(); // destructor
...
}

// C++/CLI wrapper class
ref class ManagedDog
{
NativeDog* innerObject; // unmanaged, but private, won't be seen from C#
ManagedDog(...)
{
innerObject = new NativeDog(...);
...
}

~ManagedDog() // destructor (like Dispose() in C#)
{
// free unmanaged resources
if (innerObject)
delete innerObject;
}

!ManagedDog() // finalizer (like Finalize() in C#, in case
{ // the user forgets to dispose)
~ManagedDog(); // call destructor
}
}

一切都很好,我这样使用这个类:

// in C++/CLI
// this function is called from C++ code
void MyLibrary::FeedDogNative(NativeDog* nativedog)
{
... // (***)
}
// this function is called from C#, passes on the dog to the native function
void MyLibrary::FeedDogManaged(ManagedDog^ dog)
{
NativeDog* rawdog = dog->innerObject;
MyLibrary::FeedDogNative(rawdog);
}

// C# client code
void MyFunc()
{
ManagedDog dog = new ManagedDog(...);
MyLibrary.FeedDogManaged(dog);
}

看看有什么问题?一开始我也没有,直到不时发生非常奇怪的事情。基本上,如果在调用 MyFunc() 之后程序在本地函数 FeedDogNative 中的某处被 GC 暂停(标记为 (***) 上面),它会认为托管包装可以被收集,因为它不再被使用,无论是在 C# MyFunc 中(它是一个局部变量,在 FeedDogManaged 调用之后不会被使用),也不是在 FeedDogManaged 中。因此,这实际上有时会发生。 GC 调用终结器,它删除本地狗对象,即使 FeedDogNative 还没有完成使用它!所以我的非托管代码现在使用的是已删除的指针。

我该如何防止这种情况发生?我可以想到一些方法(例如,假装在 FeedDogManaged 末尾使用 dog 的虚拟调用)但推荐的方法是什么?

最佳答案

你需要一个 GC::KeepAlive()调用您的 FeedDogManaged 函数。看起来这是一个确切的用例。

关于c# - C++/命令行界面 : preventing garbage collection on managed wrapper of unmanaged resource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4366779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com