【问题标题】:MATLAB crashes when I use malloc instead of mxMalloc当我使用 malloc 而不是 mxMalloc 时,MATLAB 崩溃
【发布时间】:2013-02-27 01:53:57
【问题描述】:

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

【问题讨论】:

  • 对我来说不会崩溃,不过我在使用 64 位 matlab (R2011a) 的 linux 上
  • 我正在使用带有 R2009b MATLAB 的 Linux Ubuntu 12.10 32 位。看来,问题出在我系统的某个地方。
  • 我不明白为什么人们继续使用旧版本的 matlab...
  • @slayton,这是因为它是唯一可以在我的 Windows 98 机器上运行的机器 :-)
  • @paxdiablo,哈哈,安装 Linux

标签: matlab malloc mex


【解决方案1】:

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

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

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


无论如何,documentation 是明确的:

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

虽然具体只提到了calloc 函数,但mxMalloc documentation 声明:

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

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


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

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

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

【讨论】:

  • 它没有抱怨将 int 分配给 double*,但它仍然在所有情况下崩溃(有和没有 stdlib.h,有和没有强制转换)
  • 感谢您的帮助。其实我用的是R2009b,有意思的是MATLAB R2009b的帮助中没有提到这句话:“不要使用ANSI C calloc函数,会导致内存对齐问题导致程序终止。”再次感谢
【解决方案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 */

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 这毫无意义。没有区别,因为参数是按值取的。你用的是什么编译器?
    猜你喜欢
    • 2011-03-31
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多