Why is mxGetPi giving an Access Violation?
1 Ansicht (letzte 30 Tage)
Ältere Kommentare anzeigen
Michael Mullen
am 24 Aug. 2016
Kommentiert: James Tursa
am 24 Aug. 2016
The attached script - which is very stripped down - works until I un-comment line 48, which uses mxGetPi, at which point I am given an access violation. I managed to get this far by allocating memory for input vectors prior to using mxGetPr/Pi (if this isn't advisable, please let me know. But it does seem to eliminate access violation errors for mxGetPr). The variable 'volume' (the first rhs variable) can be taken as 1, while I am using a vector (length 100*volume) of zeros for the second rhs input, and a vector of length 100*volume of ones for the 3rd rhs input.
How can I prevent an access violation when using mxGetPi?
#include "mex.h"
void test_function(double *out_mat,long int volume,
double *Mx_in,double *My_in,double *Mz_in)
{
long int k;
double Mxyz[3];
for (k=0; k <= 100*volume-1; ++k)
{
Mxyz[0] = Mx_in[k];
Mxyz[1] = My_in[k];
Mxyz[2] = Mz_in[k];
out_mat[k] = Mxyz[0] + Mxyz[1] + Mxyz[2];
}
}
/*************************************************************************/
// MEX FUNCTION HERE //
/*************************************************************************/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nlhs != 1){
mexErrMsgTxt("ERROR: Number of arguments does not equal 9. \n");
}
if (nrhs != 3){
mexErrMsgTxt("ERROR: Number of RHS objects is incorrect. \n");
}
double volume;
volume = mxGetScalar(prhs[0]);
double *Mx_in;
double *My_in;
double *Mz_in;
Mx_in = mxMalloc(sizeof(double) * 100*volume);
My_in = mxMalloc(sizeof(double) * 100*volume);
Mz_in = mxMalloc(sizeof(double) * 100*volume);
Mx_in = mxGetPr(prhs[1]);
Mz_in = mxGetPr(prhs[2]);
/* My_in = mxGetPi(prhs[1]); */
double *out_mat;
plhs[0] = mxCreateDoubleMatrix(100*volume,1,mxREAL);
out_mat = mxGetPr(plhs[0]);
test_function(out_mat,volume,Mx_in,My_in,Mz_in);
}
1 Kommentar
Akzeptierte Antwort
James Tursa
am 24 Aug. 2016
Bearbeitet: James Tursa
am 24 Aug. 2016
Some comments on your use of pointers and memory allocation:
Mx_in = mxMalloc(sizeof(double) * 100*volume); <-- Delete this line, it is leaked
My_in = mxMalloc(sizeof(double) * 100*volume);
Mz_in = mxMalloc(sizeof(double) * 100*volume); <-- Delete this line, it is leaked
Mx_in = mxGetPr(prhs[1]); <-- Creates a memory leak, loses the previous Mx_in
Mz_in = mxGetPr(prhs[2]); <-- Creates a memory leak, loses the previous Mz_in
/* My_in = mxGetPi(prhs[1]); */ <-- Only makes sense if the 2nd input is complex
So, if the 2nd input is real, then the result of mxGetPi(prhs[1]) will be NULL. So when you pass this into your test_function routine and access My_in[k] you will get an access violation and a crash. The reason your My_in = mxMalloc(etc) fixes that crash is because with this line added My_in now points to valid (but uninitialized) memory.
I can't really advise you what to do about My_in because I don't know what your code is supposed to do. Maybe you could put in some comments about what each input to the mex routine is, and what the calculation is supposed to be for the result. Then I could advise you on how to code it properly.
Also, I would change this check:
if (nlhs != 1){
mexErrMsgTxt("ERROR: Number of arguments does not equal 9. \n");
}
to this:
if (nlhs > 1){
mexErrMsgTxt("ERROR: Too many outputs. \n");
}
The way you have it coded, it forces the user to assign the mex output to a variable and doesn't allow then to simply call the mex function and have the result returned into ans. Even if nlhs==0, there is always room for one output to be placed in plhs[0] (so it can be returned into ans).
Also, at some point you should put in input argument checks to make sure they are the expected class, size, complexity, sparsity, etc so your code will not crash for unexpected inputs.
2 Kommentare
James Tursa
am 24 Aug. 2016
Yes, I think you got it now. If at least one of the elements of prhs[1] is complex, then there will be memory allocated for the imaginary data behind mxGetPi(prhs[1]) that is the same size as the real data behind mxGetPr(prhs[1]). Of course, some of those imaginary components might be 0. To check to see if prhs[1] is complex:
mxIsComplex(prhs[1])
does the same thing as
mxGetPi(prhs[1]) != NULL
If this test fails (meaning prhs[1] is in fact real and not complex) then your code would have to handle that case. E.g., allocate a temporary 0-filled vector to be used by your downstream code, or have different code for this case.
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Write C Functions Callable from MATLAB (MEX Files) finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!