当我使用malloc而不是mxMalloc时,MATLAB崩溃

时间:2013-02-27 01:53:58

标签: matlab malloc mex

我在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崩溃,我们将不胜感激。 感谢

3 个答案:

答案 0 :(得分:5)

首先,转换malloc的返回值(无论如何,在C中,C ++是另一回事),尤其是如果你'不包括stdlib.h - 在整数和指针大小不同的环境中,你会遇到各种各样的问题。

取消演员,看看是否抱怨将int分配给double *

如果有,请确保包含stdlib.h以获取malloc原型。


无论如何,documentation是明确的:

  

数组必须位于动态内存中;调用mxCalloc来分配这个内存。不要使用ANSI C calloc函数,这会导致内存对齐问题导致程序终止。

虽然这只是提及calloc函数,但mxMalloc documentation州:

  

mxMalloc分配足以容纳n个字节的连续堆空间。使用mxMalloc代替ANSI C malloc函数在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)的函数才起作用。