Проблемы управления памятью

Обзор

Примечание

Примеры в этой теме используют функции в чередованном комплексном API. Чтобы создать приложения с этими функциями, вызвать mex со специфичной для релиза опцией -R2018a.

Когда MEX-функция возвращает управление в MATLAB®, это возвращает результаты своих расчетов в выходных аргументах — mxArrays содержавшийся в аргументах plhs[] левой стороны. Эти массивы должны иметь временный осциллограф, не передавайте массивы, созданные с mexMakeArrayPersistent функция в plhs. MATLAB уничтожает любой mxArray созданный MEX-функцией, которая не находится в plhs. MATLAB также освобождает любую память, которая была выделена в MEX-функции с помощью mxCalloc, mxMalloc, или mxRealloc функции.

В общем случае MathWorks® рекомендует, чтобы MEX-функции уничтожили свои собственные временные массивы и освободили их собственную динамически выделенную память. Более эффективно выполнить эту очистку в исходном файле MEX, чем использовать автоматический механизм. Этот подход сопоставим с другими приложениями MATLAB API (Приложения MAT-файла, приложения механизма, и MATLAB Compiler™ сгенерировал приложения, которые не имеют никакого автоматического механизма очистки.)

Однако не уничтожайте mxArray в исходном файле MEX, когда это:

  • переданный файлу MEX в правой стороне перечисляют prhs[]

  • возвращенный в левой стороне перечисляют plhs[]

  • возвращенный mexGetVariablePtr

  • используемый, чтобы создать структуру

В этом разделе описываются ситуации, характерные для управления памятью. Мы рекомендуем, чтобы вы рассмотрели код в своих исходных файлах MEX, чтобы избегать использования этих функций в следующих ситуациях. Для получения дополнительной информации смотрите Автоматическую Очистку Временных массивов в файлах MEX и Персистентном mxArrays. Для руководства на проблемах памяти см. Стратегии Эффективного использования Памяти.

Потенциальные проблемы управления памятью включают:

Неправильное уничтожение mxArray

Не использовать mxFree уничтожать mxArray.

Пример

В следующем примере, mxFree не уничтожает объект массивов. Эта операция освобождает заголовок структуры, сопоставленный с массивом, но MATLAB все еще действует, как будто объект массивов должен быть уничтожен. Таким образом MATLAB пытается уничтожить объект массивов, и в процессе, пытается освободить свой заголовок структуры снова:

mxArray *temp = mxCreateDoubleMatrix(1,1,mxREAL);
      ...
mxFree(temp);  /* INCORRECT */

Решение

Вызвать mxDestroyArray вместо этого:

mxDestroyArray(temp);  /* CORRECT */

Неправильно Создавая Ячейку или Структуру mxArray

Не вызывать mxSetCell или mxSetField варианты с prhs[] как массив члена.

Пример

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

myfunction('hello')
/* myfunction is the name of your MEX file and your code
/* contains the following:    */

    mxArray *temp = mxCreateCellMatrix(1,1);
      ...
    mxSetCell(temp, 0, prhs[0]);  /* INCORRECT */

Решение

Сделайте копию правого аргумента стороны с mxDuplicateArray и используйте ту копию в качестве аргумента к mxSetCell (или mxSetField варианты). Например:

mxSetCell(temp, 0, mxDuplicateArray(prhs[0]));  /* CORRECT */

Создание временного mxArray с неподходящими данными

Не вызывать mxDestroyArray на mxArray чьи данные не были выделены стандартной программой API.

Пример

Если вы вызываете mxSetDoubles, mxSetComplexDoubles, или любая из введенных функций доступа к данным, задающих память, которая не была выделена mxCalloc, mxMalloc, или mxRealloc как намеченный блок данных (второй аргумент), затем когда файл MEX возвращается, MATLAB пытается освободить указатели на действительные данные и мнимые данные (если таковые имеются). Таким образом MATLAB пытается освободить память, в этом примере, от стека программы:

mxArray *temp = mxCreateDoubleMatrix(0,0,mxREAL);
double data[5] = {1,2,3,4,5};
      ...
mxSetM(temp,1); mxSetN(temp,5); mxSetDoubles(temp, data); 
/* INCORRECT */

Решение

Вместо того, чтобы использовать mxSetDoubles чтобы установить указатель данных, вместо этого, создают mxArray с правильным размером и использованием memcpy скопировать данные о стеке в буфер, возвращенный mxGetDoubles:

mxArray *temp = mxCreateDoubleMatrix(1,5,mxREAL);
double data[5] = {1,2,3,4,5};
      ...
memcpy(mxGetDoubles(temp), data, 5*sizeof(double)); /* CORRECT */

Создание потенциальных утечек памяти

Перед Версией 5.2, если вы создали mxArray с помощью одной из стандартных программ создания API и затем вы перезаписали указатель на использование данных mxSetDoubles, MATLAB все еще освободил исходную память. MATLAB больше не освобождает память.

Например:

pr = mxCalloc(5*5, sizeof(double));
... <load data into pr>
plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL);
mxSetDoubles(plhs[0], pr);  /* INCORRECT */

теперь 5*5*8 байтов утечек памяти, где 8 байтов размер double.

Можно избежать что утечка памяти путем изменения кода в:

plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL);
pr = mxGetDoubles(plhs[0]);
... <load data into pr> 

или альтернативно:

pr = mxCalloc(5*5, sizeof(double));
... <load data into pr>
plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL);
mxFree(mxGetDoubles(plhs[0]));
mxSetDoubles(plhs[0], pr);

Первое решение более эффективно.

Подобные утечки памяти могут также произойти при использовании mxSetDoubles, mxSetComplexDoubles, mxSetIr, mxSetJc, или любая из числовых введенных функций доступа к данным. Можно избежать утечек памяти путем изменения кода как описано в этом разделе.

Неправильное уничтожение структуры

Для структуры необходимо вызвать mxDestroyArray только на структуре, не на полевых массивах данных. Поле в структуре указывает на данные в массиве, используемом mxSetField или mxSetFieldByNumberкогда mxDestroyArray уничтожает структуру, она пытается пересечь вниз через себя и свободный все другие данные, включая память в массивах данных. Если вы вызываете mxDestroyArray на каждом массиве данных та же память освобождена дважды, который может повредить память.

Пример

Следующий пример создает три массива: один массив структур aStruct и два массива данных, myDataOne и myDataTwo. Имя поля one содержит указатель на данные в myDataOne, и имя поля two содержит указатель на данные в myDataTwo.

mxArray *myDataOne; 
mxArray *myDataTwo; 
mxArray *aStruct; 
const char *fields[] = { "one", "two" }; 
 
myDataOne = mxCreateDoubleScalar(1.0); 
myDataTwo = mxCreateDoubleScalar(2.0); 
 
aStruct = mxCreateStructMatrix(1,1,2,fields); 
mxSetField( aStruct, 0, "one", myDataOne ); 
mxSetField( aStruct, 1, "two", myDataTwo ); 
mxDestroyArray(myDataOne); 
mxDestroyArray(myDataTwo);
mxDestroyArray(aStruct); /* tries to free myDataOne and myDataTwo */

Решение

Команда mxDestroyArray(aStruct) уничтожает данные во всех трех массивах:

      ...
aStruct = mxCreateStructMatrix(1,1,2,fields); 
mxSetField( aStruct, 0, "one", myDataOne ); 
mxSetField( aStruct, 1, "two", myDataTwo ); 
mxDestroyArray(aStruct); 

Уничтожение памяти в деструкторе класса C++

Не используйте mxFree или mxDestroyArray функции в деструкторе C++ класса используются в MEX-функции. Если MEX-функция выдает ошибку, MATLAB очищает переменные файла MEX, как описано в Автоматической Очистке Временных массивов в файлах MEX.

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

Смотрите также

|

Похожие темы