我正在读取二进制数据文件,该文件是通过在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 回答
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的指针 . 所以这段代码
使用大写'B'是不好的,除非你重载了NeedleUSsim :: operator new()以使用mxMalloc,我不建议这样做 . 但是如果使用mxMalloc等分配了dasani的字段,那么你可能希望将它们传递给mexMakeMemoryPersistent . 如果可能的话,我建议在NeedleUSsim构造函数中做类似的事情,使其保持在mxMalloc调用附近 .
感觉好像是 mexMakeMemoryPersistent() 导致所有这些麻烦 . 我想你必须用它来指示matlab一旦完成就不要删除内存 . 但为什么matlab会删除dasani指针?如何将该指针提供给matlab以及matlab需要它做什么?
除了使dasani成为持久性指针之外,我还需要使用mxMalloc / mxCalloc分配的内存使其成员变量具有持久性,例如:
使用析构函数如下所示: