2

我在 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 会关闭。

如果我替换mallocmxMalloc,代码将毫无问题地执行。我知道最好使用 mx* 来分配内存,但我确信 malloc 和 calloc 以及 free 可以毫无问题地在 MEX 中使用。

我也删除了(双*),但它仍然崩溃。

如果让我知道为什么提到的代码会导致 MATLAB 崩溃,我们将不胜感激。谢谢

4

3 回答 3

6

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

取下演员表,看看它是否抱怨将 a 分配int给 a double *

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


无论如何,文档很清楚:

数组必须在动态内存中;调用mxCalloc分配此内存。不要使用 ANSI Ccalloc函数,这会导致内存对齐问题导致程序终止。

尽管这仅特别提到了calloc功能,但mxMalloc文档指出:

mxMalloc分配足以容纳n字节的连续堆空间。在 MATLAB 应用程序中使用mxMalloc而不是 ANSI Cmalloc函数来分配内存。

因此,文档明确禁止您所做的事情。别这样了。不要让我过来:-)


有关更多信息,有关 MatLab 使用诸如 SIMD 之类的东西进行高速数学运算的信息很多。

SIMD 可能需要比常规 C 数据类型更严格的对齐(因此比malloc保证更严格)。

这很可能是导致您的问题的原因,并且得到了文档中“可能导致内存对齐问题”评论的支持。我不完全确定是这种情况(因为我无法访问 MatLab 的源代码),但至少这是一个可行的解释。

于 2013-02-27T02:03:18.727 回答
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 */
于 2021-01-06T17:55:30.613 回答
0

为了避免其他人潜在的痛苦,在输入参数 x 上使用 mxMalloc(x) 的函数只有在 x 被声明为 const int x 时才有效,而不仅仅是 int x。

于 2020-12-06T02:04:28.800 回答