mexCallMATLAB crashes for dynamically allocated mxArrays
    조회 수: 9 (최근 30일)
  
       이전 댓글 표시
    
Could someone kindly help me fix the issue that I have in using dynamically allocated mxArrays? In the example code below, MATLAB crashes when it reaches mexCallMATLAB.
#include <mex.h>
#include <math.h>  
void   Reduce   ( mxArray *B, mxArray *&Breduced );
void   convolve ( mxArray *Ain, mxArray *Kernel, mxArray *&Aout );
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ 
      double *B = mxGetPr( prhs[0] );
      mxArray **Bt1 = new mxArray*[ 2 ];
      Bt1[0] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
      mxSetPr( Bt1[0], &B[ 0 ] );
      mxSetM ( Bt1[0], mxGetM( prhs[0] ) );
      mxSetN ( Bt1[0], mxGetN( prhs[0] ) );
      Bt1[1] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
      mxSetM ( Bt1[1], mxGetM( prhs[0] ) >> 1 );
      mxSetN ( Bt1[1], mxGetN( prhs[0] ) >> 1 );
      Reduce( Bt1[ 0 ], Bt1[ 1 ] );
      delete[] Bt1;
}
void Reduce( mxArray *B, mxArray *&Breduced )
{
    long int ijB, ijTemp, ijBreduced;
      mxArray *mask = mxCreateDoubleMatrix( 1, 5, mxREAL );
      double *maskPtr = mxGetPr( mask );
      maskPtr[0] = 0.05; 
      maskPtr[1] = 0.25; 
      maskPtr[2] = 0.4; 
      maskPtr[3] = 0.25; 
      maskPtr[4] = 0.05;
      mxArray *maskTranspose = mxCreateDoubleMatrix( 5, 1, mxREAL );
      maskTranspose = mxDuplicateArray( mask );
      mxArray *BConvolved = NULL;
      convolve( B, mask, BConvolved );
      double *BConvolvedPtr = mxGetPr( BConvolved );
      mxArray *Temp = mxCreateDoubleMatrix( 
                                  (mwSize)mxGetM(B), 
                                  (mwSize)mxGetN(B) >> 1, 
                                   mxREAL );
      double *TempPtr = mxGetPr( Temp );
      for( int j = 0; j < ((mwSize)mxGetN(B) >> 1); j++ )
          for( int i = 0; i < (mwSize)mxGetM(B); i++ ) 
          {
              ijTemp = i + (mwSize)mxGetM(B) *   j;
              ijB    = i + (mwSize)mxGetM(B) * 2*j;
              TempPtr[ ijTemp ] = BConvolvedPtr[ ijB ];
          }
      mxArray *TempConvolved = NULL;
      convolve( Temp, maskTranspose, TempConvolved );
      double *TempConvolvedPtr = mxGetPr( TempConvolved );
      double *BreducedPtr = mxGetPr( Breduced );
      for( int j = 0; j < ((mwSize)mxGetN(B) >> 1); j++ ) 
          for( int i = 0; i < ((mwSize)mxGetM(B) >> 1); i++ ) 
          {
              ijTemp      = 2*i +  (mwSize)mxGetM(B)       * j;
              ijBreduced  =   i + ((mwSize)mxGetM(B) >> 1) * j;
              BreducedPtr[ ijBreduced ] = TempConvolvedPtr[ ijTemp ];
          }
}
void convolve( mxArray *Ain, mxArray *Kernel, mxArray *&Aout )
{
    mxArray *rhs[3];
      rhs[0] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
      rhs[1] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
      rhs[2] = mxCreateString       ( "same" );
      double *ainPtr = mxGetPr( Ain );
      mxSetPr( rhs[0], ainPtr       );
      mxSetM ( rhs[0], mxGetM(Ain)  );
      mxSetN ( rhs[0], mxGetM(Ain)  );
      double *kernelPtr = mxGetPr( Kernel );
      mxSetPr( rhs[1], kernelPtr          );
      mxSetM ( rhs[1], mxGetM(Kernel)     );
      mxSetN ( rhs[1], mxGetN(Kernel)     );
      mexCallMATLAB(1, &Aout, 3, rhs, "conv2");
      mxSetPr( rhs[0], NULL ); 
      mxSetPr( rhs[1], NULL );
}
댓글 수: 0
답변 (1개)
  Geoff Hayes
      
      
 2014년 11월 24일
        AP - even if I compile the code without the call to Reduce in your mexFunction, the program still crashes (compiled on R2014a, OS X 10.8.5). Assuming the code is placed in a file named, myConv.cpp, then
 >> mex myConv.cpp
 Building with 'Xcode Clang++'.
 MEX completed successfully.
 >> myConv(magic(4))
 CRASH!
This crash, once the Reduce call has been commented out, points to a problem with the mxSetPr which uses the input parameter, prhs[0]. This is the same error experienced in a previous post of yours, so it isn't clear to me how - with this same code - you expect the code to work without crashing. Why not simplify your code in the mexFunction to the following
 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
 { 
      // create the appropriately sized output (?) matrix
      mxArray *Bt1 = 0;
      Bt1 = mxCreateNumericMatrix( 
              mxGetM(prhs[0]) >> 1, mxGetN(prhs[0]) >> 1, mxDOUBLE_CLASS, mxREAL);
      // reduce the input matrix
      Reduce(prhs[0], Bt1);
      // destroy any created arrays
      mxDestroyArray(Bt1);
 }
Note how in the above we pass prhs[0] as the first input to Reduce, and that since we create a numeric matrix, then we must destroy it. Of course, the above will require some changes to your signature for Reduce. It met change from
 void   Reduce   ( mxArray *B, mxArray *&Breduced );
to
 void   Reduce   ( const mxArray *B, mxArray *Breduced );
Note how we need to add the const qualifier for the input matrix (which is prhs[0]), and that we are no longer passing the second input parameter by reference (?). Was that the intent with the Breduced, and if so, why?
And like the signature for Reduce was changed, we must do the same for convolve, changing it from
 void   convolve ( mxArray *Ain, mxArray *Kernel, mxArray *&Aout );
to
 void   convolve ( const mxArray *Ain, mxArray *Kernel, mxArray **Aout );
Note how we need to add the const qualifier for the input matrix (which is prhs[0]), and that the output matrix is mxArray **Aout, since we expect convolve to create this matrix for us. In the calling function, we just create a null pointer to an mxArray and want convolve to create it for us. This means that we must also change the manner in which we call convolve from
 convolve( B, mask, BConvolved );
to
 convolve( B, mask, &BConvolved );
where we pass the address of the pointer to BConvolved. The same will need to be done for the other call to convolve.
Due to this, the call to mexCallMATLAB will need to change slightly from
 mexCallMATLAB(1, &Aout, 3, rhs, "conv2");
to
 mexCallMATLAB(1, Aout, 3, rhs, "conv2");
Compiling this, and calling myConv(magic(4)) works without crashing, but you will need to verify that the correct calculations are being performed.
As well, there are a number of place in the code where you are creating matrices (numeric or string) and not freeing the memory. The following lines should be added to Reduce
    // destroy arrays
    mxDestroyArray(maskTranspose);
    mxDestroyArray(mask);
    mxDestroyArray(BConvolved);
    mxDestroyArray(Temp);
    mxDestroyArray(TempConvolved);
and the following line added to convolve
    // destroy arrays
    mxDestroyArray(rhs[2]);
I've attached a version of the code that compiles (on my system anyway).
댓글 수: 0
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

