2015-05-26 3 views
0

У меня есть dll C++, которая считывает видеокадры с камеры. Эти кадры распределяются в DLL, возвращаемой с помощью указателя на вызывающего (программа C#).Как освободить память в C#, которая выделена в C++

Когда C# выполняется с определенным кадром видео, ему необходимо его очистить. Интерфейс DLL и управление памятью завернуты в одноразовый класс на C#, поэтому его легче контролировать. Однако, похоже, что память не освобождается/освобождается. Объем памяти моего процесса растет и растет, и менее чем за минуту я получаю ошибки распределения в C++ DLL, так как нет никакой памяти.

Видеокадры занимают чуть более 9 МБ каждый. Существует много кода, поэтому я просто предоставил распределение/освобождение/типы/и т. Д.

Первый: распределение в C++ необработанного буфера для байтов камеры.

dst = new unsigned char[mFrameLengthInBytes]; 

Второе: переход от исходного указателя обратно через границу DLL как неподписанные символ * и в IntPtr в C#

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

Так что теперь IntPtr передается в CTOR в VideoFrame класс. Внутри CTOR IntPtr копируется на внутренний член класса следующим образом:

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

Я понимаю, что это мелкая копия и класс в настоящее время ссылается на исходный буфер данных. Кадр используется/обрабатывается/и т. Д. Позже класс VideoFrame расположен, и для очистки памяти используется следующее.

Marshal.FreeHGlobal(this.dataPtr); 

Я подозреваю, что проблема в том, что ... DataPtr является IntPtr и C# не имеет никакого способа знать, что основной буфер на самом деле 9 МБ, правильно? Есть ли способ сказать, сколько памяти будет выпущено на тот момент? Я использую неправильный метод C#? Есть ли кто-то специально для такого рода ситуаций?

+3

VideoSource_ReleaseFrame (pFrame)? – Slugart

+0

Если память выделена в C++ dll, она также должна быть освобождена. – nikitoz

+0

API не имеет такого вызова. Его код повторного использования и был разработан для использования в других программах на C++, чтобы вы могли удалить [] и избавиться от памяти. Я не могу изменить интерфейс, но я могу изменить код. Если в C# нет способа сделать это, мне нужно будет сделать обходной путь в C++. – LawfulEvil

ответ

3

Вам необходимо вызвать соответствующий «бесплатный» метод в используемой библиотеке.

Память, выделенная через new, является частью среды выполнения C++, а вызов FreeHGlobal не будет работать. Вам нужно позвонить (так или иначе) delete[] против памяти.

Если это ваша собственная библиотека, то создайте функцию (например, VideoSource_FreeFrame), которая удалит память. Например:

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

А потом называют это из C#, проходя в IntPtr вы вернулись.

3

Вам необходимо (в C++) delete dst;. Это означает, что вам необходимо предоставить API, который может вызывать код C#, например FreeFrame(...), что делает именно это.

+0

В моем случае его удаление [], но да, мне кажется, мне нужно купить у других держателей акций и обновить API и т. Д. – LawfulEvil

0

Согласен с первым ответом. НЕ освобождайте его в коде C#, используя любые магические, литургические заклинания. Напишите метод на C++, который освободит память и вызовет его из вашего кода на C#. Не входите в привычку выделять память в одной куче (родной) и освобождаете ее от другой кучи (управляемой), это просто плохая новость.

Помните одно из правил из книги, эффективных C++: Выделите память в конструкторе и освободите его в деструкторе.И если вы не можете сделать это в деструкторе, сделайте это в методе класса, а не какую-нибудь глобальную (или даже худшую) функцию друга.

Смежные вопросы