有关奇葩的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 贡献

 

posted @ 2016-03-15 10:54  wenglabs  阅读(2456)  评论(0编辑  收藏  举报