mexCallMATLAB crashes for dynamically allocated mxArrays

1 view (last 30 days)
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 );
}

Answers (1)

Geoff Hayes
Geoff Hayes on 24 Nov 2014
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).

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!