PInvoke:在C++中分配内存,并在C#中释放内存
PInvoke: Allocate memory in C++ and free it in C#
我们使用PInvoke在C#和C++之间进行互操作。
我有一个如下所示的互操作结构,在另一侧有一个相同布局的C++结构。
[StructLayout(LayoutKind.Sequential)]
public struct MeshDataStruct : IDisposable
{
public MeshDataStruct(double[] vertices, int[] triangles , int[] surfaces)
{
_vertex_count = vertices.Length / 3;
_vertices = Marshal.AllocHGlobal(_vertex_count*3*sizeof (double));
Marshal.Copy(vertices, 0, _vertices, _vertex_count);
}
// .. extract data methods to double[] etc.
private IntPtr _vertices;
private int _vertex_count;
public void Dispose()
{
if (_vertices != IntPtr.Zero)
{
Marshal.FreeHGlobal(_vertices);
_vertices = IntPtr.Zero;
}
}
}
现在我想添加第二个ctor
public MeshDataStruct(bool filled_in_by_native_codee)
{
_vertex_count = 0;
_vertices = IntPtr.Zero;
}
然后用C++编写一个允许C++填充数据的方法。这将允许我们对输入和输出数据使用相同的结构。。。
然而,据我所知,AllocHGlobal
在C#和C++/Cli中可用,但不是纯C++。
所以我的问题是:如何在C++中分配内存,以便通过调用Marshal.FreeHGlobal(...)
在C#端安全地释放内存?
传统上,这总是以糟糕的结果告终,Microsoft CRT使用HeapCreate()创建了自己的堆,为C或C++程序中的malloc/new调用提供服务。无法在C#中释放这样的内存,您没有堆句柄。
然而,从VS2012中包含的CRT(msvcr120.dll及以上版本)开始,情况发生了变化。它现在使用默认的进程堆,即GetProcessHeap()返回的进程堆。也是Marshal.Aloc/FreeHGlobal()使用的。所以,如果本机代码不使用调试分配器(crtdbg.h),您现在可以尝试一下了。小心放弃调试选项。
pinvokemarshaller没有改变,也不能。如果它必须释放内存,比如作为函数返回值返回的数组或字符串,那么它将调用CoTaskMemFree()。从你的问题中还不清楚哪一个适用。如果有疑问,并且您在本机代码中可以选择,那么CoTaskMemAlloc()与C#代码中的Marshal.FreeCoTaskMem()配对不会出错。
来自文档:
AllocHGlobal是Marshal中的两种内存分配方法之一班(Marshal.AllocCoTaskMem是另一个。)此方法公开Kernel32.dll.中的Win32 LocalAlloc函数
当AllocHGlobal调用LocalAlloc时,它传递一个LMEM_FIXED标志导致所分配的存储器被锁定到位。此外,分配的内存不是零填充的。
因此,您可以从非托管代码调用LocalAlloc
来分配内存,从托管代码中调用Marshal.FreeHGlobal
来取消分配内存。同样,LocalFree
也可以在非托管代码中用于取消分配使用Marshal.AllocHGlobal
分配的内存。
正如文档所暗示的,您可以对CoTaskMemAlloc/CoTaskMemFree
和Marshal.AllocCoTaskMem/FreeCoTaskMem
执行同样的操作。
话虽如此,你这样做是在为摔倒做准备。将分配和解除分配保持在相同的模块中要干净得多。以这种方式混合匹配很可能会导致对谁负责释放内存产生很大的困惑。
- 包含矢量指针的结构的内存释放问题
- Valgrind 声称内存释放中的自由空间太多
- 当 C 和 C++ 中严格要求内存释放时
- C++ 中指针变量的内存释放
- 德克内存释放
- 临时对象 c++ 的内存释放
- C 全局对象变量内存释放
- C++矢量动态内存释放/删除
- 从 cv::Mat 初始化的 IplImage 的内存释放
- SWIG类型映射中的内存释放
- STL容器中的内存释放
- QWebView内存释放
- 内存释放 C++
- 大返回值(如字符串)的内存释放如何在C++中发生
- 重新分配之前的内存释放
- Linux C++ 中的内存释放
- VS2012编译器奇怪的内存释放问题
- 调试断言失败!错误的内存释放
- 负责 COM 互操作中的内存释放
- imread命令后OpenCV矩阵内存释放