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

s k*_*s k 0 c# c++ interop memory-management

我有 C#(核心)和 C++(非托管 DLL)之间的代码互操作。

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

在 C++ using 中分配的内存new需要在 C++ using中释放delete

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

Rem*_*eau 5

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

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

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

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

以及LocalAlloc()状态的文档:

要释放内存,请使用 LocalFree 函数。使用 GlobalFree 释放用 LocalAlloc 分配的内存是不安全的。

这是什么Marshal.FreeHGlobal()用途:

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

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

同样,Marshal该类也有一个Marshal.AllocCoTaskMem()方法:

此方法公开 COM CoTaskMemAlloc 函数,称为 COM 任务内存分配器。

分配的内存通过以下CoTaskMemAlloc()方式释放CoTaskMemFree()

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

这是什么Marshal.FreeCoTaskMem()用途:

FreeCoTaskMem 公开 COM CoTaskMemFree 函数,该函数释放所有字节,以便您不能再使用 ptr 参数指向的内存。

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

现在,话虽如此,C++ 用于其newdelete运算符的内存管理器是实现定义的。不保证(或可能性)new使用LocalAlloc()CoTaskMemAlloc(),或delete使用LocalFree()CoTaskMemFree()

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