首页 文章

mexFunction中的内存管理问题

提问于
浏览
1

我正在读取二进制数据文件,该文件是通过在Matlab m文件中调用以下行来编写的:

disp(sprintf('template = %d', fwrite(fid, template_1d, 'uint8')));

AFAIK,uint8与BYTE类型,unsigned char和unsigned short的大小相同 . 因此,我在由Matlab调用的mex函数中实例化的C类中的文件读取方法中编写了以下代码:

template1D = (unsigned short*) malloc(Nimgs*sizeof(unsigned short));
printf("template1D = %d\n", fread(template1D, sizeof(unsigned short), Nimgs, dfile));

以下是我在类析构函数的辅助函数中释放此成员变量的方法:

free((void*) template1D);

在主mex函数中,当我通过调用mexMakeMemoryPersistent()函数在mex函数完成后没有实例化类对象以在内存中持久化时,template1D被正确清除而没有来自Matlab的分段错误消息 . 但是,如果我确实将类实例化为在内存中保留,如下所示:

if (!dasani)
{
    dasani = new NeedleUSsim;
    mexMakeMemoryPersistent((void*) dasani);
    mexAtExit(ExitFcn);
}

使用ExitFcn:

void ExitFcn()
{
    delete dasani;
}

然后,当我在free((void *)template1D);时,Matlab给出了一个关于分段错误的错误消息 . 我检查了内存大小,它们似乎是一致的 . 对于malloc / calloc / free函数,当我将C项目作为Matlab mex函数执行时,我正在使用Matlab的mxMalloc / mxCalloc / mxFree函数 .

根据这个描述,你有什么进一步的建议可以解决这个问题,并确保将来不会发生这种情况(或者至少知道如何在未来处理类似的问题)?

提前致谢 .

----------------------------附加--------------------- ---------------------------------

下面的代码块基本上显示了我的mex文件的数据 . mex文件基本上是一个可执行文件,在Matlab中运行,并使用一些Matlab头文件从C / C代码编译 .

void ExitFcn()
{
    delete dasani;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    needle_info pin;

    // check number of i/o if they are correct
    if (nrhs != NUMIN)
    {
        mexErrMsgTxt("Invalid number of input arguments");
    }
    else if (nlhs != NUMOUT)
    {
        mexErrMsgTxt("Invalid number of output arguments");
    }

    // check if the input is noncomplex
    if (mxIsComplex(NEEDLE))
    {
        mexErrMsgTxt("Input must be a noncomplex scalar integer.");
    }

    // check if the dimensions of the needle information is valid
    int needlerows, needlecols;
    needlerows = mxGetM(NEEDLE);
    needlecols = mxGetN(NEEDLE);
if (needlerows < 1 || needlecols < 6)
{
        mexErrMsgTxt("Needle information's dimensions are invalid");
    }

    float *needlePoint, *yPoint ;

    // retrieving current needle information
    // order of the variables are always as follows:
    // r, theta, l, rho, alpha, beta
    needlePoint = (float*) mxGetData(NEEDLE) ;
    pin.r = needlePoint[0];
    pin.theta = needlePoint[1];
    pin.l = needlePoint[2];
    pin.rho = needlePoint[3];
    pin.alpha = needlePoint[4];
    pin.beta = needlePoint[5];

    //// read the file inputs
    **//if (!dasani)
    //{
    //  dasani = new NeedleUSsim;
    //  mexMakeMemoryPersistent((void*) dasani);
    //  mexAtExit(ExitFcn);
    //}
    dasani = new NeedleUSsim;
    delete dasani;**

    // sending an useless output for now (get rid of this if not conceptually needed
    plhs[0] = mxCreateNumericMatrix(1,1,mxSINGLE_CLASS,mxREAL) ;
    yPoint = (float*) mxGetData(plhs[0]) ;
    *yPoint = 1;
}

如果用户在命令行或m-file脚本的任何地方调用“mexfunction”,则此代码将在构建/编译后运行 . 由“**”包围的片段(当我试图加粗片段时)是我正在看的问题 . 从第二次看片段开始,我可能会在与Matlab内存不同的内存中为dasani指针分配内存(因为内存的范围仅限于C mex函数,另一个内存空间的范围可见Matlab程序) . 否则,我不确定为什么Matlab会抱怨这个问题 .

3 回答

  • 1

    MEX API支持C和C . 因为C没有try / catch或析构函数,所以C MEX函数无法在发生错误时直接清理内存 . 因此,MATLAB在内部列表中跟踪内存分配例程(mxMalloc,mxCalloc,mxRealloc,mxFree和所有返回mxArrays的mxCreate *函数)的结果 . 如果在执行MEX函数期间发生错误(通过直接调用mexErrMsgIdAndTxt,或者使用类似mexEvalString的函数调用错误的MATLAB代码),则MATLAB将自动释放任何基于mx的已分配内存 . 但是,当MEX函数正常终止时,MATLAB还将释放由MEX函数分配的任何基于mx的内存 . 在析构函数之前,这对于MEX作者来说是一种便利,尽管在现代C世界中它可能会变得非常烦人 .

    有时候,就像这个问题一样,你不希望MATLAB自动释放内存 . 在这种情况下,您必须为mxArrays使用mexMakeMemoryPersistent或mexMakeArrayPersistent .

    如果最初使用mxMalloc,mxCalloc或mxRealloc分配,则应该只传递指向mexMakeMemoryPersistent的指针 . 所以这段代码

    dasani = new NeedleUSsim;
    mexMakeMemoryPersistent((void*) dasani);
    

    使用大写'B'是不好的,除非你重载了NeedleUSsim :: operator new()以使用mxMalloc,我不建议这样做 . 但是如果使用mxMalloc等分配了dasani的字段,那么你可能希望将它们传递给mexMakeMemoryPersistent . 如果可能的话,我建议在NeedleUSsim构造函数中做类似的事情,使其保持在mxMalloc调用附近 .

  • 4

    感觉好像是 mexMakeMemoryPersistent() 导致所有这些麻烦 . 我想你必须用它来指示matlab一旦完成就不要删除内存 . 但为什么matlab会删除dasani指针?如何将该指针提供给matlab以及matlab需要它做什么?

  • 0

    除了使dasani成为持久性指针之外,我还需要使用mxMalloc / mxCalloc分配的内存使其成员变量具有持久性,例如:

    if (!dasani)
    {
        dasani = new NeedleUSsim;
        mexMakeMemoryPersistent((void*) dasani->tplL);
        mexMakeMemoryPersistent((void*) dasani->tplR);
        mexMakeMemoryPersistent((void*) dasani->tplRho_deg);
        mexMakeMemoryPersistent((void*) dasani->tplAlpha_deg);
        mexMakeMemoryPersistent((void*) dasani->tplBeta_deg);
        mexMakeMemoryPersistent((void*) dasani->hashTb);
        mexMakeMemoryPersistent((void*) dasani->template1D);
        mexAtExit(ExitFcn);
    }
    

    使用析构函数如下所示:

    void NeedleUSsim::Deallocate()
    {
        free((void*) tplR);     free((void*) tplL);
        free((void*) tplRho_deg);   free((void*) tplAlpha_deg);
        free((void*) tplBeta_deg);
        free((void*) hashTb);   
        free((void*) template1D);
    }
    

相关问题