笔记
本主题中的示例使用交错复杂API中的函数。要使用这些函数构建应用程序,请调用墨西哥人
使用特定版本选项-R2018A
.
当MEX函数返回到MATLAB的控件时®,它在输出参数中返回计算结果-mxArray
S包含在左边参数中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例程分配。
如果你打电话mxSetDoubles
那mxsetComplepledouble.
,或指定未分配的内存的任何类型的数据访问功能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);
第一种解决方案更有效。
使用时也可能发生类似的内存泄漏mxSetDoubles
那mxsetComplepledouble.
那mxSetIr
那mxSetJc
,或任何数字类型的数据访问函数。您可以通过更改本节中描述的代码来避免内存泄漏。
对于一个结构,您必须致电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);
不要使用mxfree.
或mxDestroyArray
在MEX函数中使用的类的C ++析构函数中的函数。如果MEX函数抛出错误,则MATLAB清除MEX文件变量,如下所述MEX文件中的临时阵列自动清理.
如果发生导致对象超出作用域的错误,MATLAB将调用c++析构函数。直接在析构函数中释放内存意味着MATLAB和析构函数释放相同的内存,这可能会损坏内存。