主要内容

内存管理问题

概述

笔记

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

当MEX函数返回到MATLAB的控件时®,它在输出参数中返回计算结果-mxArrayS包含在左边参数中PLHS [].这些阵列必须具有临时范围,因此请勿通过阵列mexMakeArrayPersistent函数PLHS..MATLAB破坏任何mxArray由不在的MEX函数创建PLHS..属性还可以释放在MEX函数中分配的任何内存mxcalloc.mxMalloc, 或者mxrealloc.功能。

一般来说,MathWorks.®建议MEX功能破坏自己的临时数组并释放自己的动态分配内存。在源MEX文件中执行此清除比依赖于自动机制更有效。这种方法与其他MATLAB API应用程序(MAT文件应用程序,引擎应用程序以及MATLAB编译器™生成的应用程序,没有任何自动清理机制。)

但是,不要摧毁一个mxArray在源MEX文件中:

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

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

  • 返回的mexgetvarifienceptr.

  • 用于创建一个结构

本节介绍了对内存管理特定的情况。我们建议您查看源MEX文件中的代码,以避免在以下情况下使用这些功能。有关更多信息,请参阅MEX文件中的临时阵列自动清理持久mxArrays.有关记忆问题的指导,请参阅有效利用记忆的策略

潜在的记忆管理问题包括:

不破坏的mxArray

不使用mxfree.摧毁一个mxArray

例子

在以下示例中,mxfree.不销毁数组对象。这个操作释放了与数组关联的结构头,但MATLAB仍然像需要销毁数组对象那样操作。因此,MATLAB试图销毁数组对象,并在此过程中,试图再次释放其结构头:

mxarray * temp = mxcreatedoublematrix(1,1,mxreal);... MXFREE(TEMP);/ *不正确* /

解决方案

称呼mxDestroyArray反而:

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

构建细胞或结构不正确mxArray

不要打电话mxsetcell.mxsetfield.变种prhs []作为成员数组。

例子

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

myfunction('hello') /* myfunction是你的MEX文件的名字,你的代码/*包含以下内容:...mxSetCell(临时0 prhs [0]);/ *不正确* /

解决方案

复制右边的参数mxduplicatearray.并使用该副本作为参数mxsetcell.(或者mxsetfield.变异)。例如:

mxsetcell(temp,0,mxduplicatearray(prhs [0]));/* 正确的 */

创造临时mxArray数据不当

不要打电话mxDestroyArray在AN.mxArray其数据未被API例程分配。

例子

如果你打电话mxSetDoublesmxsetComplepledouble.,或指定未分配的内存的任何类型的数据访问功能mxcalloc.mxMalloc, 或者mxrealloc.作为预期的数据块(第二个参数),然后当MEX文件返回时,MATLAB试图释放指向真实数据和假想数据(如果有的话)的指针。因此,在这个例子中,MATLAB试图从程序堆栈中释放内存:

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

解决方案

而不是使用mxSetDoubles要设置数据指针,请创建数据指针mxArray具有正确的尺寸和使用memcpy.将堆栈数据复制到返回的缓冲区中mxgetdoubles.

mxArray *temp = mxCreateDoubleMatrix(1,5,mxREAL); / /显示真实值Double data[5] = {1,2,3,4,5};...memcpy (mxGetDoubles(临时)数据,5 * sizeof(双));/* 正确的 */

创建潜在的内存泄漏

在5.2之前,如果您创建了一个mxArray使用其中一个API创建例程,然后使用mxSetDoubles,Matlab仍然释放了原来的记忆。Matlab不再释放内存。

例如:

pr = mxcalloc(5 * 5,sizeof(双));... <将数据加载到PR> PLHS [0] = mxcreatedoublematrix(5,5,mxreal);mxsetdoubles(plhs [0],pr);/ *不正确* /

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

您可以避免将代码更改为以下内存泄漏:

plhs [0] = mxCreateDoubleMatrix (5 5 mxREAL);公关= mxGetDoubles (plhs [0]);...加载数据到pr>

或者:

pr = mxcalloc(5 * 5,sizeof(双));... <将数据加载到PR> PLHS [0] = mxcreatedoublematrix(5,5,mxreal);mxfree(mxgetdoubles(plhs [0]));mxsetdoubles(plhs [0],pr);

第一种解决方案更有效。

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

不正当地摧毁了一个结构

对于一个结构,您必须致电mxDestroyArray只有在结构上,不在现场数据阵列上。结构中的一个字段指向所用阵列中的数据mxsetfield.mxsetfieldbynumber..什么时候mxDestroyArray销毁结构,尝试遍历自身并释放所有其他数据,包括数据阵列中的内存。如果你打电话mxDestroyArray在每个数据阵列上,相同的内存被释放两次可能损坏内存。

例子

以下示例创建三个数组:一个结构数组透镜和两个数据阵列,mydataone.myDataTwo.字段名包含指向中数据的指针mydataone.和字段名称包含指向中数据的指针myDataTwo

mxarray * mydataone;mxarray * mydatatwo;mxarray * astruct;const char *字段[] = {“一个”,“两个”};mydataone = mxcreatedoublescalar(1.0);mydatatwo = mxcreatedoublescalar(2.0);aStruct = mxCreateStructMatrix(1, 1, 2,字段);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,字段);mxSetField(aStruct, 0, "one", myDataOne);mxSetField(aStruct, 1, "two", mydatattwo);mxdestroyarray(astruct);

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

不要使用mxfree.mxDestroyArray在MEX函数中使用的类的C ++析构函数中的函数。如果MEX函数抛出错误,则MATLAB清除MEX文件变量,如下所述MEX文件中的临时阵列自动清理

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

也可以看看

|

相关的话题