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

Обзор

Примечание

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

Когда MEX-функция возвращает управление в MATLAB®, это возвращает результаты своих вычислений в выходных аргументах — mxArray s содержавшийся в аргументах 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, чтобы избегать использования этих функций в следующих ситуациях. Для получения дополнительной информации смотрите Автоматическую Очистку Временных массивов и Персистентного 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, как описано в Автоматической Очистке Временных массивов.

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

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

|

Похожие темы

Для просмотра документации необходимо авторизоваться на сайте