如何释放C ++中分配的内存

时间:2015-05-26 16:47:01

标签: c# c++ memory-management dll memory-leaks

我有一个C ++ dll正在从相机中读取视频帧。这些帧在通过指向调用者(C#程序)的指针返回的DLL中分配。

当C#完成特定的视频帧时,需要将其清理干净。 DLL接口和内存管理包装在C#中的一次性类中,因此更容易控制。但是,似乎内存不会被释放/释放。我的进程的内存占用增长和增长,不到一分钟,我在C ++ DLL中得到分配错误,因为没有任何内存。

视频帧每个都超过9 MB。有很多代码,所以我只提供分配/解除分配/类型/等。

首先:在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#免费方法吗?有没有专门针对这种情况?

3 个答案:

答案 0 :(得分:3)

您需要在您正在使用的库中调用相应的“免费”方法。

通过new分配的内存是C ++运行时的一部分,调用FreeHGlobal将不起作用。你需要对内存进行delete[]调用(<1}}。

如果这是您自己的库,则创建一个删除内存的函数(例如VideoSource_FreeFrame)。例如:

void VideoSource_FreeFrame(unsigned char *buffer)
{
  delete[] buffer;
}

然后从C#调用它,传入你回来的IntPtr

答案 1 :(得分:3)

你需要(在c ++中)delete dst;。这意味着您需要提供C#代码可以调用的API,例如FreeFrame(...),它就是这样做的。

答案 2 :(得分:0)

我同意第一个答案。不要使用任何神奇的礼仪咒语以C#代码释放它。在C ++中编写一个释放内存的方法,并从C#代码中调用它。不要养成在一个堆(本机)中分配内存并将其释放到另一个堆(托管)的习惯,这只是个坏消息。

记住本书有效C ++中的一条规则:在构造函数中分配内存,并在析构函数中释放。如果您无法在析构函数中执行此操作,请在类内方法中执行此操作,而不是在某些全局(甚至更糟)的朋友函数中执行此操作。