如何在c#中释放c++中分配的内存
How to free memory in C# that is allocated in C++
我有一个c++ dll,它正在从相机读取视频帧。这些帧在DLL中被分配,DLL通过指向调用者(c#程序)的指针返回。
当c#处理完一个特定的视频帧时,它需要清理它。在c#中,DLL接口和内存管理被封装在一个一次性类中,因此更容易控制。然而,似乎内存没有被释放。我的进程的内存占用越来越大,在不到一分钟的时间里,我在c++ DLL中得到分配错误,因为没有任何内存剩余。
视频帧每帧超过9mb。有很多代码,所以我只提供分配/释放/类型等。
First:在c++中为相机字节分配原始缓冲区
dst = new unsigned char[mFrameLengthInBytes];
第二步:从原始指针返回到跨DLL边界的unsigned char *和c# IntPtr类型
IntPtr pFrame = VideoSource_GetFrame(mCamera, ImageFormat.BAYER);
return new VideoFrame(pFrame, .... );
所以现在IntPtr被传递到VideoFrame类的CTOR中。在CTOR内部,IntPtr被复制到类的内部成员,如下所示:
IntPtr dataPtr;
public VideoFrame(IntPtr pDataToCopy, ...)
{
...
this.dataPtr = pDataToCopy;
}
我的理解是,这是一个浅拷贝,类现在引用原始数据缓冲区。框架被使用/处理/等等。随后,处置VideoFrame类,并使用以下代码清理内存。
Marshal.FreeHGlobal(this.dataPtr);
我怀疑问题是……dataPtr是一个IntPtr, c#没有办法知道底层缓冲区实际上是9 MB,对吧?有没有办法告诉它在那个点要释放多少内存?我是否使用了错误的c# free方法?有专门针对这种情况的吗? 您需要调用您正在使用的库中相应的"free"方法。
通过new
分配的内存是c++运行时的一部分,调用FreeHGlobal
将不起作用。您需要调用(一种或另一种方式)delete[]
对内存。
如果这是您自己的库,那么创建一个删除内存的函数(例如VideoSource_FreeFrame
)。如:
void VideoSource_FreeFrame(unsigned char *buffer)
{
delete[] buffer;
}
然后从c#调用它,传入你得到的IntPtr
。
您需要(在c++中)delete dst;
。这意味着你需要提供一个c#代码可以调用的API,比如FreeFrame(...)
,它就是这样做的。
我同意第一个答案。不要在c#代码中释放它,使用任何神奇的、仪式性的咒语。用c++写一个释放内存的方法,然后在c#代码中调用它。不要养成在一个堆(本机)分配内存并释放另一个堆(托管)的习惯,这只是坏消息。
记住书中有效的c++规则之一:在构造函数中分配内存,在析构函数中释放内存。如果不能在析构函数中完成,那么就在类内方法中完成,而不是在某个全局(甚至更糟)友元函数中完成。
- 在c++中为我自己的基于指针的数组分配内存的正确方法
- 给定一个指向堆分配内存的指针,智能指针实现如何为其找到合适的释放函数?
- 如果 const 不分配内存,为什么我可以获取 const 的地址?
- 在函数中分配内存时出现问题
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- constexpr new 如何分配内存?
- 在构造函数中分配内存失败是如何冒泡的
- LLVM 传递以在特定地址分配内存
- CudaMalloc 在分配内存时失败
- 为什么它在不分配内存的情况下工作正常
- 为什么在正确解除分配内存时出现内存泄漏?
- 如何通过 malloc 为队列数组分配内存?
- vector是否为std::移动的对象连续分配内存
- 删除类成员的动态分配内存的最佳方法是什么
- 唯一指针是否在堆或堆栈上分配内存?
- 如果不分配内存,我如何能够为变量创建和分配值?
- std::initializer_list 堆是否分配内存?
- 如何按顺序或在指定的地址分配内存?
- 是否可以使用 malloc 为类对象分配内存?
- 迭代器是否分配内存(如指针)?