我在MATLAB中编写了以下代码:
#include <string.h>
#include <stdlib.h>
#include "mex.h"
#include "matrix.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]){
double* x = (double*)malloc(5 * sizeof(*x));
int k;
for(k=0;k<5;k++)
x[k] = k;
mxArray* p1 = mxCreateDoubleMatrix(5, 1, mxREAL);
mxSetPr(p1, x);
}
在没有输入或输出的情况下调用函数。这段代码除了初始化某个向量之外什么也没做。我理解代码有严重的内存泄漏,但除了内存泄漏之外,当我调用函数时,MATLAB关闭。
如果我将malloc
替换为mxMalloc
,代码将没有问题地执行。我理解使用mx*来分配内存是可取的,但是我确信在MEX中使用malloc和callloc以及free不会有任何问题。
我也删除了(double*),但它仍然崩溃。
如果让我知道为什么提到的代码导致MATLAB崩溃,我将不胜感激。由于
首先,不要强制转换malloc
的返回值(无论如何,在C中,c++是另一个问题),特别是如果你不包括stdlib.h -你会遇到各种各样的问题在环境中,你的整数和指针是不同的大小。
取下石膏,看看它是否抱怨将int
分配给double *
。
如果有,请确保包含stdlib.h
以获得malloc
原型。
无论如何,文档都很清楚:
数组必须在动态内存中;调用
mxCalloc
来分配内存。不要使用ANSI Ccalloc
函数,这可能会导致内存对齐问题,从而导致程序终止。
虽然上面只特别提到了calloc
函数,但mxMalloc
文档指出:
mxMalloc
分配足够容纳n
字节的连续堆空间。在MATLAB应用程序中使用mxMalloc
代替ANSI Cmalloc
函数来分配内存。
因此,您所做的是文档明确禁止的。别再这样了。别逼我过去:-)
对于进一步的信息,有相当多的信息漂浮在re MatLab使用SIMD之类的东西进行高速数学。
SIMD可能需要比常规C数据类型更严格的对齐要求(因此比malloc
保证的更严格)。
这很可能是导致问题的原因,并且在文档中的"which can cause memory alignment issues"注释中得到支持。我不完全确定这是这种情况(因为我无法访问MatLab的源代码),但至少这是一个可行的解释。
发布的代码实际上有两个问题:
double* x = (double*)malloc(5 * sizeof(*x));
:
mxArray* p1 = mxCreateDoubleMatrix(5, 1, mxREAL);
mxSetPr(p1, x); /* This leaks memory AND causes a crash */
第一个问题是别人已经发布的。您永远不能将本机C/c++内存(malloc, calloc, realloc, new等)附加到mxArray上。这样做会搞砸MATLAB内存管理器,并最终导致MATLAB试图释放此内存时崩溃。您只能将来自MATLAB API函数的内存附加到mxArray。
第二个问题是存在内存泄漏。mxCreateDoubleMatrix(5,1, mxREAL)调用在mxArray中的数据指针后面分配内存。此数据指针不在垃圾收集列表中。当您随后调用mxSetPr(p1, x)时,您将擦除该数据指针并将其替换为x,因此您对该数据指针的唯一访问将丢失并泄漏内存。因为这个数据指针不在垃圾收集列表中,所以当mex函数返回给调用者时,它不会被释放。它只能通过重新启动MATLAB来恢复。这里有一些方法可以在不导致崩溃和内存泄漏的情况下正确地编写代码:
更改为mxMalloc和mxFree原始数据指针:
double* x = (double*)mxMalloc(5 * sizeof(*x));
:
mxArray* p1 = mxCreateDoubleMatrix(5, 1, mxREAL);
mxFree(mxGetData(p1)); /* Free the original data pointer */
mxSetPr(p1, x); /* Attach MATLAB API generated pointer */
更改为mxMalloc并以空矩阵开始:
double* x = (double*)mxMalloc(5 * sizeof(*x));
:
mxArray* p1 = mxCreateDoubleMatrix(0, 0, mxREAL);
mxSetPr(p1, x); /* Attach MATLAB API generated pointer */
mxSetM(p1, 5); /* Set row size */
mxSetN(p1, 1); /* Set column size */
不要单独分配…只使用原始数据指针:
mxArray* p1 = mxCreateDoubleMatrix(5, 1, mxREAL);
double* x = (double*)mxGetData(p1);
/* Then use x downstream in your code */
为了节省其他人可能的痛苦时间,在输入参数x上使用mxMalloc(x)的函数只有在x被声明为const int x时才能工作,而不仅仅是int x。