有关奇葩的mex编程时的matlab出现栈内存错误的问题
错误提示信息
(ntdll.dll) (MATLAB.exe中)处有未经处理的异常:0xC0000374:堆已损坏
该错误的表现是,matlab调用.mexw64函数时,第一次调用正常,第二次调用出现matlab闪退、或者卡死无反应的错误。
参考方案
我遇到同样的问题,我代码里写了一个数组,定义了1个大小。然后又对他赋50个值。报这样一个错。
后来我调整了数组的初始化的大小,就解决了这个问题了。
方案2
出错原因:越界了,覆盖了你的堆的内存块
解决方案3 本人的解决方案
出现这个问题,一定是你自己释放错了栈空间。而且,由于是在程序第二次运行时出错的,所以,肯定是释放了matlab本身应该自己处理的栈内存。
经过细密的思考,终于花费了4个小时候,找到了原因。
// calll style: [ismax,ev,n1,n2,p1,p2]=compute_line_points(derivates,mode); void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { int img_height, img_width,fieldNumber[5], i; double *derivates_gaussian[5]; const char *field_names_gaussian_derivatives[]={"h_r","h_c","h_rr","h_rc","h_cc"}; mxArray *m_rx,*m_ry,*m_rxx,*m_rxy,*m_ryy; float *ev,*nx,*ny,*px,*py; byte *ismax; double th_low,th_high,road_mode=2; /* Check for proper number of arguments */ if ( nrhs < 1 || nrhs > 2) mexErrMsgTxt("READLAS.MEX: wrong number of input arguments."); if ( nlhs > 6 ) mexErrMsgTxt("READLAS.MEX: wrong number of output arguments."); /* Obtain the inputs information */ if (nrhs==2) road_mode = *(mxGetPr(prhs[1])); else road_mode=2; // get field number for (i=0;i<5;i++) fieldNumber[i] = mxGetFieldNumber(prhs[0],field_names_gaussian_derivatives[i]); //mxGetFieldNameByNumber // get matrix m_rx=mxGetFieldByNumber(prhs[0],0,fieldNumber[0]); m_ry=mxGetFieldByNumber(prhs[0],0,fieldNumber[1]); m_rxx=mxGetFieldByNumber(prhs[0],0,fieldNumber[2]); m_rxy=mxGetFieldByNumber(prhs[0],0,fieldNumber[3]); m_ryy=mxGetFieldByNumber(prhs[0],0,fieldNumber[4]); img_height=mxGetM(m_rx); img_width=mxGetN(m_rx); if (img_width<=1 || img_height<=1) mexErrMsgTxt("非法的影像大小."); /* sCreate matrix for the derivates double matrix in c++ */ for ( i = 0; i < 5; i++) derivates_gaussian[i]=(double*)malloc(sizeof(double)*img_height*img_width); /* Assign pointers to each input and output */ // data in (2 style can do it, and it will be shown below ) // you should notice the memcpy(derivates_gaussian[0],mxGetPr(m_rx),sizeof(double)*img_height*img_width); memcpy(derivates_gaussian[1],mxGetPr(m_ry),sizeof(double)*img_height*img_width); memcpy(derivates_gaussian[2],mxGetPr(m_rxx),sizeof(double)*img_height*img_width); memcpy(derivates_gaussian[3],mxGetPr(m_rxy),sizeof(double)*img_height*img_width); memcpy(derivates_gaussian[4],mxGetPr(m_ryy),sizeof(double)*img_height*img_width); //here can free the m_rx,m_ry,m_rxx /*if (m_rx!=NULL) mxDestroyArray(m_rx); if (m_ry!=NULL) mxDestroyArray(m_ry); if (m_rxx!=NULL) mxDestroyArray(m_rxx); if (m_rxy!=NULL) mxDestroyArray(m_rxy); if (m_ryy!=NULL) mxDestroyArray(m_ryy);*/ // data information in the local verible for (i=0;i<5;i++) derivates_gaussian[i]=storeMemoryStyleChange(derivates_gaussian[i],img_height,img_width); // data out // BUG Warnnning , mxUINT8_CLASS is equal to usigned char, not matalb's mxCHAR_CLASS plhs[0] = mxCreateNumericMatrix(img_height,img_width, mxUINT8_CLASS,mxREAL); // ismax plhs[1] = mxCreateNumericMatrix(img_height,img_width, mxSINGLE_CLASS,mxREAL); // ev plhs[2] = mxCreateNumericMatrix(img_height,img_width, mxSINGLE_CLASS,mxREAL); // nx plhs[3] = mxCreateNumericMatrix(img_height,img_width, mxSINGLE_CLASS,mxREAL); // ny plhs[4] = mxCreateNumericMatrix(img_height,img_width, mxSINGLE_CLASS,mxREAL); // px plhs[5] = mxCreateNumericMatrix(img_height,img_width, mxSINGLE_CLASS,mxREAL); // py // get data out ptr ismax=(byte*)mxGetData(plhs[0]); // ideas come form the explore.c ev=(float*)mxGetData(plhs[1]); nx=(float*)mxGetData(plhs[2]); ny=(float*)mxGetData(plhs[3]); px=(float*)mxGetData(plhs[4]); py=(float*)mxGetData(plhs[5]); // chanage the data stroe type before processing ismax=storeMemoryStyleChange(ismax,img_height,img_width); ev=storeMemoryStyleChange(ev,img_height,img_width); nx=storeMemoryStyleChange(nx,img_height,img_width); ny=storeMemoryStyleChange(ny,img_height,img_width); px=storeMemoryStyleChange(px,img_height,img_width); py=storeMemoryStyleChange(py,img_height,img_width); /* Call the distedt subroutine. */ th_low=0.05; th_high=0.20; compute_line_points(derivates_gaussian,ismax,ev,nx,ny,px,py,img_width,img_height,th_low,th_high,(long)road_mode); /* change the data saves order style form c++ to matlab variable */ ismax =storeMemoryStyleChange(ismax,img_width,img_height); // you can notice the order and location of M, N ev =storeMemoryStyleChange(ev,img_width,img_height); nx =storeMemoryStyleChange(nx,img_width,img_height); ny =storeMemoryStyleChange(ny,img_width,img_height); px =storeMemoryStyleChange(px,img_width,img_height); py =storeMemoryStyleChange(py,img_width,img_height); /* done */ // free the data in abouts pointers for ( i = 0; i < 5; i++) if (derivates_gaussian[i]!=NULL) free(derivates_gaussian[i]); // null the the data out pointers if (ismax!=NULL) ismax=NULL; if (ev!=NULL) ev=NULL; if (nx!=NULL) nx=NULL; if (ny!=NULL) ny=NULL; if (px!=NULL) px=NULL; if (py!=NULL) py=NULL; }
出错的原因,在于红色黑体相关的代码段,根本原因在于红色的代码段。因为m_rx没有使用mexCreateXXXMatrix创建,而仅仅是通过如下语句创建、
m_rx=mxGetFieldByNumber(prhs[0],0,fieldNumber[0]);
而这个语句是matlab调用时直接压栈的方式传递过来的数据,mxArray 是主调函数空间的变量,而m_rx只是获得该prhs[0]中结构体的一个成员变量,如果直接后来(上文中红色代码段)通过mxDestroyArray 进行删除,难免在该.mexw64动态链接库返回时造成 matlab中的栈损坏。当matlab第二次运行时,已经损坏的栈空间的隐藏问题,就直接暴露出来了,造成了第一次能直接正常调用,而第二次调用时出现问题的奇葩经历。
终于能正常的出结果了。
总结经验:
(1)遇到栈内存空间错误,一定是,越界了,非法释放覆盖了你的堆的内存块。而且是free了错误地址(由calloc、malloc创建的栈空间)的栈内存,或者delete释放了错误的
内存地址(new创建的)。
(2)本不应该在被掉函数空间释放主调函数空间的内存,结果在错误的调用空间内释放了错误的内存地址。
(3)遇到问题,不能乱投医,更不要揪着不放去浪费时间。多思考,多向高手请教,多查资料。
CSUNKING 贡献
没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。