当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《我是否需要在非托管代码中删除通过Marshal.PtrToStructure封送的结构?》经验,为你挑选了2个好方法。

我有这个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++"删除"?

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



1> GBegen..:

正如Erik所说,元帅确实意味着复制,但我不认为他回答了你问题的要点.

你需要保持pData本机指针,直到MyDataStructure被GCed?没有.

封送后,MyDataStructure实例foo包含pData指向的结构的副本.你不需要再持有pData了.为了避免内存泄漏,您必须将该pData传递给另一个将删除它的非托管函数,并且可以在编组后立即完成,无论您保留MyDataStructure实例多长时间.



2> Erik Forbes..:

是的,在这种情况下,马歇尔意味着复制; 因此,您需要在非托管代码中释放内存.对PtrToStructure执行的所有调用都是从pData指向的内存位置读取目标结构"MyDataStructure"大小所指示的字节数.

当然,细节取决于'MyDataStructure'的确切含义(您在MyDataStructure中使用任何FieldOffset或StructLayout属性) - 但最终结果是PtrToStructure的返回是数据的副本.

正如GBegen在答案中指出的那样,我没有回答你问题的要点.是的,您需要在非托管代码中删除结构的非托管副本,但不需要保留pData - 您可以在调用PtrToStructure完成后立即删除非托管副本.

PS:我编辑了我的帖子以包含这些信息,以便将答案合并到一个帖子中 - 如果有人赞成这个答案,请upvote GBegen的回答以及他的贡献.

推荐阅读
李桂平2402851397
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有