我在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 *来分配内存是可取的,但我确信malloc和calloc以及free都可以在MEX中使用而没有任何问题。
我也删除了(double *),但它仍然崩溃了。
如果让我知道为什么提到的代码会导致MATLAB崩溃,我们将不胜感激。 感谢
答案 0 :(得分:5)
首先,不转换malloc
的返回值(无论如何,在C中,C ++是另一回事),尤其是如果你'不包括stdlib.h - 在整数和指针大小不同的环境中,你会遇到各种各样的问题。
取消演员,看看是否抱怨将int
分配给double *
。
如果有,请确保包含stdlib.h
以获取malloc
原型。
无论如何,documentation是明确的:
数组必须位于动态内存中;调用
mxCalloc
来分配这个内存。不要使用ANSI Ccalloc
函数,这会导致内存对齐问题导致程序终止。
虽然这只是提及calloc
函数,但mxMalloc
documentation州:
mxMalloc
分配足以容纳n
个字节的连续堆空间。使用mxMalloc
代替ANSI Cmalloc
函数在MATLAB应用程序中分配内存。
因此,文档明确禁止您正在做的事情。停止这样做。不要让我过来: - )
有关详细信息,MatLab使用SIMD等数据进行高速数学运算的信息非常多。
SIMD可能需要比常规C数据类型要求更严格的对齐(因此比malloc
保证更严格)。
这很可能是导致问题的原因,并且受文档中“可能导致内存对齐问题”注释的支持。我不是完全确定是这种情况(因为我无法访问MatLab的源代码),但它至少是一个可行的解释。
答案 1 :(得分:2)
发布的代码实际上有两个问题:
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 */
答案 2 :(得分:0)
为节省其他人的潜在痛苦,仅在将x声明为const int x而不是int x的情况下,在输入参数x上使用mxMalloc(x)的函数才起作用。