3 views (last 30 days)

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);

}

James Tursa
on 24 Aug 2016

Edited: James Tursa
on 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.

James Tursa
on 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.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/300801-why-is-mxgetpi-giving-an-access-violation#comment_386951

⋮## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/300801-why-is-mxgetpi-giving-an-access-violation#comment_386951

Sign in to comment.