我正在读取二进制数据文件,该文件是通过在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函数中,当mex函数通过调用mexMakeMemoryPersistent()函数完成后没有实例化类对象在内存中持久化时,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会抱怨这个问题。
答案 0 :(得分:4)
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调用附近。
答案 1 :(得分:1)
感觉好像是 mexMakeMemoryPersistent()导致所有这些麻烦。我想你必须用它来指示matlab一旦完成就不要删除内存。但为什么matlab会删除dasani指针?如何将该指针提供给matlab以及matlab需要它做什么?
答案 2 :(得分: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); }