我是否需要删除通过非托管代码中的 Marshal.PtrToStructure 封送的结构?

StackOverflow https://stackoverflow.com/questions/497133

  •  20-08-2019
  •  | 
  •  

我有这个 C++ 代码:

extern "C" __declspec(dllexport) VOID AllocateFoo(MY_DATA_STRUCTURE** foo)
{
    *foo = new MY_DATA_STRUCTURE;

    //do stuff to foo
}

然后在 C# 中我这样调用该函数:

[DllImport("MyDll.dll")]
static extern void AllocateFoo(out IntPtr pMyDataStruct);

...

MyDataStructure GetMyDataStructure()
{
    IntPtr pData;
    ManagedAllocateFooDelegate(out pData);

    MyDataStructure foo = (MyDataStructure)Marshal.PtrToStructure(pData, typeof(MyDataStructure));
    return foo;
}

其中 MyDataStructure 是一个与 MY_DATA_STRUCTURE 相对应的结构(而不​​是类),并且成员被适当地编组。

所以问题:当 MyDataStructure 被 GC 时,我是否需要存储 pData,然后在非托管代码中再次释放它?MSDN 对于 Marshal.PtrToStructure(IntPtr, Type) 的说法是:“元帅数据从不受管理的内存块到指定类型的新分配的托管对象。”在那句话中,“马歇尔”的意思是“复制”吗?在这种情况下,我需要保留 (IntPtr pData) 然后将其传递给非托管代码(在 MyDataStructure 析构函数中),以便我可以执行 C++“删除”?

我已经搜索过,但找不到足够明确的答案。

有帮助吗?

解决方案

由于埃里克说,元帅确实意味着副本,但我不认为他回答你的问题的要点。

您是否需要守住的pData本地指针,直到MyDataStructure是GCed?否。

在编组,你的MyDataStructure例如,FOO,包含结构的副本由pData所指向。你不必守住的pData任何更长的时间。为了避免内存泄漏,必须传递的pData到另一个非托管函数,将其删除,并可以封送处理后立即进行,无论你持有到MyDataStructure实例有多长。

其他提示

是的,在这种情况下,Marshall 的意思是复制;因此,您需要在非托管代码中释放内存。对 PtrToStructure 的所有调用都是从 pData 指向的内存位置读取由目标结构“MyDataStructure”的大小指示的字节数。

当然,详细信息取决于“MyDataStructure”的具体外观(您是否在 MyDataStructure 中使用任何 FieldOffset 或 StructLayout 属性) - 但最终结果是 PtrToStructure 返回的是数据的副本。

作为 格贝根 指出在 他的回答, ,我没有回答你问题的要点。是的,您需要在非托管代码中删除结构的非托管副本,但是不需要,您不需要保留 pData - 您可以在对 PtrToStructure 的调用完成后立即删除非托管副本。

附:我编辑了我的帖子以包含此信息,以便将答案合并到一篇帖子中 - 如果有人赞成这个答案,请也赞成 GBegen 的答案,以表彰他的贡献。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top