Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to free memory in C# that is allocated in C++

I have a C++ dll which is reading video frames from a camera. These frames get allocated in the DLL returned via pointer to the caller (a C# program).

When C# is done with a particular frame of video, it needs to clean it up. The DLL interface and memory management is wrapped in a disposable class in C# so its easier to control things. However, it seems like the memory doesn't get freed/released. The memory footprint of my process grows and grows and in less than a minute, I get allocation errors in the C++ DLL as there isn't any memory left.

The video frames are a bit over 9 MB each. There is a lot of code, so I'll simply provide the allocation/deallocations/types/etc.

First : Allocation in C++ of raw buffer for the camera bytes.

dst = new unsigned char[mFrameLengthInBytes];

Second : transfer from the raw pointer back to across the DLL boundary as an unsigned char * and into an IntPtr in C#

IntPtr pFrame = VideoSource_GetFrame(mCamera, ImageFormat.BAYER);
return new VideoFrame(pFrame, .... );

So now the IntPtr is passed into the CTOR of the VideoFrame class. Inside the CTOR the IntPtr is copied to an internal member of the class as follows :

IntPtr dataPtr;
public VideoFrame(IntPtr pDataToCopy, ...)
{
    ...
    this.dataPtr = pDataToCopy;
}

My understanding is that is a shallow copy and the class now references the original data buffer. The frame is used/processed/etc. Later, the VideoFrame class is disposed and the following is used to clean up the memory.

Marshal.FreeHGlobal(this.dataPtr);

I suspect the problem is that... dataPtr is an IntPtr and C# has no way to know that the underlying buffer is actually 9 MB, right? Is there a way to tell it how much memory to release at that point? Am I using the wrong C# free method? Is there one specifically for this sort of situation?

like image 576
LawfulEvil Avatar asked Dec 25 '22 18:12

LawfulEvil


1 Answers

You need to call the corresponding "free" method in the library you're using.

Memory allocated via new is part of the C++ runtime, and calling FreeHGlobal won't work. You need to call (one way or the other) delete[] against the memory.

If this is your own library then create a function (eg VideoSource_FreeFrame) that deletes the memory. Eg:

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

And then call this from C#, passing in the IntPtr you got back.

like image 123
Sean Avatar answered Dec 27 '22 09:12

Sean