Примечание
Примеры в этой теме используют функции в чередованном комплексном API. Чтобы создать приложения с этими функциями, вызвать mex
со специфичной для релиза опцией -R2018a
.
Когда MEX-функция возвращает управление в MATLAB®, это возвращает результаты своих расчетов в выходных аргументах — mxArray
s содержавшийся в аргументах plhs[]
левой стороны. Эти массивы должны иметь временный осциллограф, не передавайте массивы, созданные с
mexMakeArrayPersistent
функция в plhs
. MATLAB уничтожает любой mxArray
созданный MEX-функцией, которая не находится в plhs
. MATLAB также освобождает любую память, которая была выделена в MEX-функции с помощью mxCalloc
, mxMalloc
, или mxRealloc
функции.
In general, 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);
Не используйте mxFree
или mxDestroyArray
функции в деструкторе C++ класса используются в MEX-функции. Если MEX-функция выдает ошибку, MATLAB очищает переменные файла MEX, как описано в Автоматической Очистке Временных массивов в файлах MEX.
Если ошибка происходит, который вызывает объект выйти из осциллографа, MATLAB вызывает деструктор C++. Освобождение памяти непосредственно в деструкторе означает, что и MATLAB и деструктор освобождают ту же память, которая может повредить память.