MATLAB: Matlab crashed when call mexCallMATLAB

mex; mexcallmatlab

I want to create a new sparse matrix and pass the value of the input sparse matrix to it, and then call mexCallMATLAB to get its transpose. The code crashed,
#include <stdio.h>
#include <stdlib.h>
#include <mex.h>
#include <math.h>
#include <time.h>
#include <string.h>
extern void mexFunction(int iNbOut, mxArray *pmxOut[],
int iNbIn, const mxArray *pmxIn[])
{
mxArray *A, *B;
double *d,*p,*pin,*out;
mwSize m,n,nzmax;
mwIndex *ir, *jc;
m = mxGetM(pmxIn[0]);
n = mxGetN(pmxIn[0]);
nzmax = mxGetNzmax(pmxIn[0]);
ir = mxGetIr(pmxIn[0]);
jc = mxGetJc(pmxIn[0]);
pin = mxGetPr(pmxIn[0]);
A = mxCreateSparse(m, n, nzmax, mxREAL);
mxSetIr(A, ir);
mxSetJc(A, jc);
mxSetPr(A, pin);
d = mxGetPr(A);
B = mxCreateSparse(m, n, nzmax, mxREAL);
mexCallMATLAB(1, &B, 1, &A, "transpose");
p = mxGetPr(B);
pmxOut[0] = mxCreateNumericArray(1 , nzmax, mxSINGLE_CLASS,mxREAL);
out = mxGetPr(pmxOut[0]);
for(mwSize i = 0; i < nzmax; i++)
{
out[i] = p[i];
mexPrintf("pmxOut = %f", out[i]);
}
}

Best Answer

(1) These lines are wrong:
ir = mxGetIr(pmxIn[0]);
jc = mxGetJc(pmxIn[0]);
pin = mxGetPr(pmxIn[0]);
A = mxCreateSparse(m, n, nzmax, mxREAL);
mxSetIr(A, ir);
mxSetJc(A, jc);
mxSetPr(A, pin);
You cannot attach pointers (pr,pi,ir,jc,dims) obtained from one mxArray to another mxArray. This is in effect creating a type of "shared data copy" of the mxArray, but you are doing it in a manner that the MATLAB Memory Manager knows nothing about. When the first mxArray gets destroyed, all of the data pointers become invalid because they are freed. So when the second mxArray gets used or destroyed, those invalid data pointers get accessed and MATLAB crashes. If you really needed a shared data copy of the mxArray (which it does not appear that you really do), here is how to go about it using an undocumented API function:
mxArray *mxCreateSharedDataCopy(const mxArray *); /* Undocumented API function prototype */
:
A = mxCreateSharedDataCopy(pmxIn[0]);
(2) The output of mexCallMATLAB is not something you create ahead of time. E.g., these lines:
B = mxCreateSparse(m, n, nzmax, mxREAL);
mexCallMATLAB(1, &B, 1, &A, "transpose");
B will be created from scratch by the mexCallMATLAB call. You do not create a "place-holder" for it ahead of time. The only thing you have done with the above code is to create a memory leak because the handle to the sparse matrix B created by the mxCreateSparse call gets overwritten by the mexCallMATLAB call. (Actually, the memory leak is temporary because the garbage collection will clean up this error for you). Get rid of that first line.
If you are just trying to get the transpose of the input, then do it directly (no need for the "A" copy). E.g.,
mexCallMATLAB(1, &B, 1, (mxArray **)pmxIn, "transpose");
(3) This will crash MATLAB:
double *d,*p,*pin,*out;
:
pmxOut[0] = mxCreateNumericArray(1 , nzmax, mxSINGLE_CLASS,mxREAL);
out = mxGetPr(pmxOut[0]);
for(mwSize i = 0; i < nzmax; i++)
{
out[i] = p[i];
mexPrintf("pmxOut = %f", out[i]);
}
You create a single class mxArray pmxout[0], but then use a double pointer to access its data area in a loop. That will give garbage results at first and then crash MATLAB because you will run off the end of the allocated memory. You can't use a double pointer to access single data. Also you should be using mxCreateNumericMatrix with those inputs, not mxCreateNumericArray.
It seems like this is all you are trying to do:
mxArray *B;
double *p;
float *out;
mwSize nzmax;
nzmax = mxGetNzmax(pmxIn[0]);
mexCallMATLAB(1, &B, 1, (mxArray **)pmxIn, "transpose");
p = mxGetPr(B);
pmxOut[0] = mxCreateNumericMatrix(1 , nzmax, mxSINGLE_CLASS,mxREAL);
out = (float *) mxGetData(pmxOut[0]);
for(mwSize i = 0; i < nzmax; i++)
{
out[i] = p[i];
mexPrintf("pmxOut = %f\n", out[i]);
}
mxDestroyArray(B);