用C ++代码删除C#中分配的内存

问题描述 投票:0回答:1

我在C#(核心)和C ++(非托管DLL)之间互操作。

使用Marshal.AllocHGlobal()在C#中分配的内存需要使用Marshal.FreeHGlobal()在C#中释放。

使用new在C ++中分配的内存需要使用delete在C ++中释放。

由于GC不再跟踪这些内存处理程序,我可以随时随地使用deleteFreeHGlobal()吗?

c# c++ memory-management interop
1个回答
1
投票

不,您不能仅使用任何想要释放内存的方法。您必须使用要使用的分配器requires。只有分配给定内存块的内存管理器才知道如何正确释放该内存块。

例如,Marshal.AllocHGlobal()的文档说明:

此方法从Kernel32.dll公开Win32 LocalAlloc函数。>]。>

AllocHGlobal调用LocalAlloc时,它将传递一个LMEM_FIXED标志,这将导致分配的内存被锁定在适当的位置。另外,分配的内存不是零填充。

以及Marshal.AllocHGlobal()的文档说明:

要释放内存,请使用LocalFree功能

。使用GlobalFree释放用LocalAlloc分配的内存是不安全的。

LocalAlloc()使用什么:

FreeHGlobal从Kernel32.DLL公开LocalFree函数,该函数释放所有字节,以便您不再可以使用hglobal指向的内存。

因此,允许C#代码使用LocalAlloc()分配内存,然后允许C ++代码使用Marshal.FreeHGlobal()释放该内存。相反,对于C ++代码,使用Marshal.FreeHGlobal()分配内存,然后使C#代码使用Marshal.AllocHGlobal()释放该内存。

同样,LocalFree()类也具有LocalAlloc(LMEM_FIXED)方法:

此方法公开COM CoTaskMemAlloc函数

,它被称为COM任务内存分配器。

Marshal.FreeHGlobal()分配的内存已由Marshal释放:

释放先前通过调用CoTaskMemAlloc或CoTaskMemRealloc函数分配的任务内存块。

Marshal.AllocCoTaskMem()使用的是什么:

FreeCoTaskMem公开COM CoTaskMemFree函数

,它将释放所有字节,因此您将无法再使用ptr参数指向的内存。

因此,允许C#代码使用Marshal.AllocCoTaskMem()分配内存,然后允许C ++代码使用CoTaskMemAlloc()释放该内存。相反,对于C ++代码,使用CoTaskMemAlloc()分配内存,然后使C#代码使用CoTaskMemFree()释放该内存。

现在,这么说,C ++用于其CoTaskMemFree()Marshal.FreeCoTaskMem()运算符的内存管理器是实现定义的

。无法保证(或不可能)Marshal.FreeCoTaskMem()使用Marshal.AllocCoTaskMem()CoTaskMemFree(),或CoTaskMemAlloc()使用Marshal.FreeCoTaskMem()new

因此,C#释放用delete分配的任何内存,或C ++释放new C#分配的任何内存都是不合法的。

© www.soinside.com 2019 - 2024. All rights reserved.