主要内容

内存管理问题

概述

请注意

本主题中的示例使用交错复杂API中的函数。要使用这些函数构建应用程序,请调用墨西哥人使用特定于发行版的选项-R2018a

当一个MEX函数返回控制到MATLAB®,它在输出参数中返回其计算结果mxArrayS包含在左边的参数中plhs []。类创建的数组必须具有临时作用域,因此不要传递使用mexMakeArrayPersistent函数plhs。MATLAB破坏任何mxArray由不在的MEX函数创建plhs。方法释放在MEX函数中分配的任何内存mxCallocmxMalloc,或mxRealloc功能。

一般来说,MathWorks®建议MEX函数销毁它们自己的临时数组并释放它们自己动态分配的内存。在源MEX文件中执行这种清理比依赖于自动机制更有效。这种方法与其他MATLAB API应用程序(mat文件应用程序、引擎应用程序和MATLAB编译器™生成的应用程序,没有任何自动清理机制。)

但是,不要破坏mxArray在源MEX文件中:

  • 传递给右边列表中的MEX文件prhs []

  • 在左侧列表中返回plhs []

  • 返回的mexGetVariablePtr

  • 用于创建一个结构

本节描述特定于内存管理的情况。我们建议您检查源MEX文件中的代码,以避免在以下情况下使用这些函数。有关更多信息,请参见自动清除MEX文件中的临时数组持久mxArrays。有关内存问题的指导,请参见有效使用内存的策略

潜在的内存管理问题包括:

不恰当地销毁mxArray

不要使用mxFree摧毁…mxArray

例子

在下面的例子中,mxFree不销毁数组对象。该操作释放了与数组相关的结构头,但MATLAB仍然像需要销毁数组对象一样运行。因此,MATLAB试图销毁数组对象,并在此过程中,试图再次释放其结构头:

mxArray *temp = mxCreateDoubleMatrix(1,1,mxREAL);…mxFree(临时);/*不正确*/

解决方案

调用mxDestroyArray而不是:

mxDestroyArray(临时);/*正确*/

错误地构建单元格或结构mxArray

不要打电话mxSetCellmxSetField变异与prhs []作为成员数组。

例子

在下面的示例中,当MEX文件返回时,MATLAB将破坏整个单元格数组。由于这包括单元格的成员,因此这隐式地破坏了MEX文件的输入参数。这可能会导致一些奇怪的结果,通常与调用者工作区的损坏有关,如果使用的右侧参数是临时数组(例如,字面量或表达式的结果):

myfunction('hello') /* myfunction是您的MEX文件和代码的名称/*包含以下内容:*/ mxArray *temp = mxCreateCellMatrix(1,1);…mxSetCell(temp, 0, prhs[0]);/*不正确*/

解决方案

复制右边的论点mxDuplicateArray然后用那个拷贝作为参数mxSetCell(或mxSetField变异)。例如:

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

创建临时对象mxArray资料不正确

不要打电话mxDestroyArray在一个mxArray它的数据不是由API例程分配的。

例子

如果你打电话mxSetDoublesmxSetComplexDoubles,或指定未分配的内存的任何类型化数据访问函数mxCallocmxMalloc,或mxRealloc作为预期的数据块(第二个参数),然后当MEX文件返回时,MATLAB尝试释放指向真实数据和虚构数据(如果有的话)的指针。因此,在本例中,MATLAB试图从程序堆栈中释放内存:

mxArray *temp = mxCreateDoubleMatrix(0,0,mxREAL);双数据[5]= {1,2,3,4,5};…mxSetM (temp, 1);mxSetN(临时、5);mxSetDoubles(临时、数据);/*不正确*/

解决方案

而不是使用mxSetDoubles要设置数据指针,请创建mxArray使用合适的尺寸和用途memcpy返回的缓冲区中复制堆栈数据mxGetDoubles

mxArray *temp = mxCreateDoubleMatrix(1,5,mxREAL);双数据[5]= {1,2,3,4,5};…memcpy(mxGetDoubles(temp), data, 5*sizeof(double));/*正确*/

造成潜在的内存泄漏

在版本5.2之前,如果您创建了mxArray使用API创建例程之一,然后覆盖指向数据的指针mxSetDoubles, MATLAB仍然释放了原有的内存。MATLAB不再释放内存。

例如:

pr = mxCalloc(5*5, sizeof(double));… plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL);mxSetDoubles (plhs[0]、公关);/*不正确*/

现在泄漏5*5*8字节的内存,其中8字节是a的大小

您可以通过更改代码来避免内存泄漏:

plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL);pr = mxGetDoubles(plhs[0]);…<将数据加载到数据库>

或者:

pr = mxCalloc(5*5, sizeof(double));… plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL);mxFree (mxGetDoubles (plhs [0]));mxSetDoubles (plhs[0]、公关);

第一种解决方案更有效。

在使用时也会发生类似的内存泄漏mxSetDoublesmxSetComplexDoublesmxSetIrmxSetJc,或任何数值类型的数据访问函数。您可以通过更改本节中描述的代码来避免内存泄漏。

不当破坏建筑物

对于结构,必须调用mxDestroyArray只在结构上,而不是字段数据数组上。结构中的字段指向所使用的数组中的数据mxSetFieldmxSetFieldByNumber。当mxDestroyArray破坏结构,它尝试遍历自身并释放所有其他数据,包括数据数组中的内存。如果你打电话mxDestroyArray在每个数据数组上,相同的内存被释放两次,这可能会破坏内存。

例子

下面的示例创建了三个数组:一个结构数组aStruct还有两个数据数组,myDataOnemyDataTwo。字段名一个中数据的指针myDataOne,以及字段名两个中数据的指针myDataTwo

mxArray * myDataOne;mxArray * myDataTwo;mxArray * aStruct;Const char *fields[] = {"one", "two"};myDataOne = mxCreateDoubleScalar(1.0);mydatattwo = mxCreateDoubleScalar(2.0);aStruct = mxCreateStructMatrix(1,1,2,fields);mxSetField(aStruct, 0, "one", myDataOne);mxSetField(aStruct, 1, "two", mydatattwo);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", mydatattwo);mxDestroyArray (aStruct);

在c++类析构函数中销毁内存

不要使用mxFreemxDestroyArray函数中使用的类的c++析构函数。如果mex -函数抛出错误,MATLAB将清理mex文件变量,如自动清除MEX文件中的临时数组

如果发生导致对象超出作用域的错误,MATLAB将调用c++析构函数。直接在析构函数中释放内存意味着MATLAB和析构函数释放相同的内存,这可能会破坏内存。

另请参阅

|

相关的话题