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

Law*_*vil 4 c# c++ dll memory-leaks memory-management

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

当 C# 处理特定的视频帧时,它需要清理它。DLL 接口和内存管理封装在 C# 中的一次性类中,因此更易于控制。但是,似乎内存没有被释放/释放。我的进程的内存占用越来越大,在不到一分钟的时间里,我在 C++ DLL 中出现分配错误,因为没有任何内存可用。

每个视频帧有点超过 9 MB。有很多代码,所以我将简单地提供分配/释放/类型/等。

第一:在 C++ 中为相机字节分配原始缓冲区。

dst = new unsigned char[mFrameLengthInBytes];
Run Code Online (Sandbox Code Playgroud)

第二:从原始指针返回到跨 DLL 边界作为 unsigned char * 并传输到 C# 中的 IntPtr

IntPtr pFrame = VideoSource_GetFrame(mCamera, ImageFormat.BAYER);
return new VideoFrame(pFrame, .... );
Run Code Online (Sandbox Code Playgroud)

所以现在 IntPtr 被传递到 VideoFrame 类的 CTOR 中。在 CTOR 内部,IntPtr 被复制到类的内部成员,如下所示:

IntPtr dataPtr;
public VideoFrame(IntPtr pDataToCopy, ...)
{
    ...
    this.dataPtr = pDataToCopy;
}
Run Code Online (Sandbox Code Playgroud)

我的理解是这是一个浅拷贝,该类现在引用原始数据缓冲区。框架被使用/处理/等。之后,VideoFrame类被释放,下面用来清理内存。

Marshal.FreeHGlobal(this.dataPtr);
Run Code Online (Sandbox Code Playgroud)

我怀疑问题在于... dataPtr 是一个 IntPtr 而 C# 无法知道底层缓冲区实际上是 9 MB,对吗?有没有办法告诉它此时要释放多少内存?我是否使用了错误的 C# 免费方法?有没有专门针对这种情况的?

Sea*_*ean 7

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

通过分配的内存new是 C++ 运行时的一部分,调用FreeHGlobal将不起作用。您需要delete[]针对内存调用(一种或另一种方式)。

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

void VideoSource_FreeFrame(unsigned char *buffer)
{
  delete[] buffer;
}
Run Code Online (Sandbox Code Playgroud)

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