With mxMalloc() and mxSetDoubles(), mex function crash matlab
Mostrar comentarios más antiguos
I try to build a mex interface for a C function r8mat_expm1() that calculates matrix exponential,
double *r8mat_expm1 ( int n, double a[] );
Where n is the dimension and a is the matrix.
My mex function my_expm.c is as follows,
void mexFunction(int nlhs,mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *tmpResult;
double *inputMat;
int numRows;
numRows = mxGetM(prhs[0]);
inputMat = mxGetPr(prhs[0]);
tmpResult = mxMalloc(numRows*numRows*sizeof(*tmpResult));
tmpResult = r8mat_expm1(numRows, inputMat); // calculate matrix exponential
plhs[0] = mxCreateDoubleMatrix(numRows, numRows, mxREAL);
mxSetDoubles(plhs[0], tmpResult);
mxFree(tmpResult);
}
Which parse the input and call the computational routine r8mat_expm1().
After building on linux, I use
c=my_expm(2,[1,0;0,2]') % this is problematic, thanks Bruno Luong for pointing out
to run the compiled function. However, it just crashes matlab, and "Segmentation fault (core dumped) matlab" appears on linux terminal.
I suspect this is related to mxMalloc() and mxSetDoubles(). When I did not use these two functions, matlab will not crash. I chose to use mxSetDoubles() to fix an error, as suggested in this post.
I also tried another suggestion in that post, i.e. change r8mat_expm1() from
double *r8mat_expm1 ( int n, double a[] );
to
void r8mat_expm1 ( int n, double a[], doule output[] );
to avoid return all zeros error, but it still return all zeros.
So what is the problem behind this and how can I fix this crash error or get the right ouput instead of all zeros?
3 comentarios
Steven Lord
el 29 de Dic. de 2020
Is your goal to write a function to compute the matrix exponential or is your goal to compute the matrix exponential? If the latter, consider simply calling the expm function in MATLAB. [Even if you want to or are required to write the function yourself (for a homework assignment, perhaps) you can check your results against expm.]
Bruno Luong
el 29 de Dic. de 2020
He did compare his code againts expm.
Xingwang Yong
el 30 de Dic. de 2020
Respuesta aceptada
Más respuestas (2)
Bruno Luong
el 26 de Dic. de 2020
You must not call
mxFree(tmpResult);
Since the data is attached to the output.
4 comentarios
Xingwang Yong
el 26 de Dic. de 2020
Bruno Luong
el 26 de Dic. de 2020
Editada: Bruno Luong
el 26 de Dic. de 2020
Then you have other problem in the code r8mat_expm1.
Xingwang Yong
el 26 de Dic. de 2020
Xingwang Yong
el 26 de Dic. de 2020
Bruno Luong
el 26 de Dic. de 2020
You seem to call
mxGetM(prhs[0])
To get dimensions of the first parameter of calling
c=my_expm(2,[1,0;0,2]')
which is 2 and not the 2x2 matrix.
Who knows what else. The mex code seem to have quality issue, which is not tolerable and resulting crash.
7 comentarios
Xingwang Yong
el 26 de Dic. de 2020
Xingwang Yong
el 26 de Dic. de 2020
Bruno Luong
el 26 de Dic. de 2020
Editada: Bruno Luong
el 26 de Dic. de 2020
i have no idea since you don't post anything related to your function
tmpResult = mxMalloc(numRows*numRows*sizeof(*tmpResult));
tmpResult = r8mat_expm1(numRows, inputMat)
The fact that you allocate the pointer, don't use it as input of the function, then return another pointer telling me that you don't know what are pointers and how to manipulate them.
As I said the code has ùany flaws (I just detect free of them with the small snip you have posted).
Xingwang Yong
el 27 de Dic. de 2020
Bruno Luong
el 27 de Dic. de 2020
Editada: Bruno Luong
el 27 de Dic. de 2020
I think James has answered many question you raised already.
First, r8mat_expm1 use MALLOC to allocate resulting array "e", see the code of
double *r8mat_identity_new ( int n )
...
a = ( double * ) malloc ( n * n * sizeof ( double ) );
...
return a;
Your claim "The function r8mat_expm1() does not use malloc() for the result" is just plain wrong.
You are not allowed to assign a data array of an mxArray allocated with generic C MALLOC. You have to use mxMalloc.
The safest modification is to do exactly what he advises
#include <string.h> // for memcpy( )
#include <stdlib.h> // for free( )
double *tmpResult;
double *inputMat;
double *pr;
int numRows;
numRows = mxGetM(prhs[0]);
inputMat = mxGetDoubles(prhs[0]);
tmpResult = r8mat_expm1(numRows, inputMat); // calculate matrix exponential
plhs[0] = mxCreateDoubleMatrix(numRows, numRows, mxREAL);
pr = mxGetDoubles(plhs[0]);
memcpy(pr,tmpResult,numRows*numRows*sizeof(double));
free(tmpResult); // use free( ) for native C/C++ allocated memory
Obviously you are not the owner of r8mat_expm1, If I was you I would avoid to change r8mat_expm1 in case the authors of those function updates the code in the futur.
"if I do not use mxMalloc() for tmpResutl, this would give right result to tmpResult in mex fucntion although the result returned to matlab is wrong."
The fact that you use mxMalloc before calling r8mat_expm1 is just make memory leaks (you allocate but then throw it away since the original pointer is lost after function returns). And beside it is still not allowed since r8mat_expm1 uses MALLOC.
Xingwang Yong
el 27 de Dic. de 2020
Editada: Xingwang Yong
el 27 de Dic. de 2020
Bruno Luong
el 27 de Dic. de 2020
Sorry, you are right I make a typo. Shoul read "The fact that you use mxMalloc before calling r8mat_expm1 "
Categorías
Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


