C# IntPtr 作为 class 的成员,不能删除指针

C# IntPtr as a member of a class, cannot delete pointer

你好程序员,

我有一个关于 C# 指针的问题。我不知道如何获取代码 运行.

因此,在我的 WPF 项目中有一个 Class MainViewModel,其中包含一个 IntPtr。

private IntPtr m_context;

从 C 接口加载数据时会填充此上下文(该接口执行“return new class_name()”)。我这样称呼它:

this.m_context = interface_context_create();

使用时,我想删除上下文。这也是一个接口方法。我希望它像这样调用 与上面创建的方法相同 (!!):

unsafe
{
    interface_context_free(&this.m_context);
}

interface_context_free(..) 在 c 接口端有一个 class_name**,所以这就是我需要使用 & 的原因。我的 C# 端的接口是正确的,因为我的 test1() 方法(见下文)确实正确创建和释放。

这在 interface_context_free(&this.m_context); 处给出以下错误:

CS:0212 你只能在固定语句初始值设定项

中获取未固定表达式的地址

如果我这样声明它,那么它绝对可以正常工作!!!:

public void test1()
{
  IntPtr iptr = interface_context_create();

  unsafe
  {
    interface_context_free(&iptr);
  }
}

如何释放m_context,这两种情况有什么区别??

与垃圾收集器有关。对于 GC,您应该将字段标记为 non-moving。

fixed (void* myIntPtr = &intPtr)
{
    interface_context_free(myIntPtr);
}

详情在这里: https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/fixed-statement

这实际上是一个非常简单的修复。

你不能&this.m_context的原因是因为那个变量在内存中没有固定。因此,虽然您有一个指向该变量的地址在非托管 space 中浮动,但 GC 可能会介入并将该变量移动到其他地方,从而使该地址无效。如果包含字段 m_context 的对象实例在垃圾收集周期中幸存下来并因此被提升到新的生成并因此移动到新的内存位置,则可能会发生这种情况。

修复非常简单:首先将 IntPtr 值复制到局部变量中。堆栈上的变量不会四处移动,只要您不让该地址超出变量的范围,就可以获取它们的地址。

所以不是这个:

unsafe
{
    interface_context_free(&this.m_context);
}

就这样做:

unsafe
{
    IntPtr temp = this.m_context;
    interface_context_free(&temp);
}

请注意,如果 interface_context_free 函数采用指向变量的指针的原因是它不仅释放了从变量引用的对象,而且还修改了变量内容本身,例如将其设置为指向null,您必须将修改后的临时变量复制回字段中:

unsafe
{
    IntPtr temp = this.m_context;
    interface_context_free(&temp);
    this.m_context = temp;
}