Mex file crash after many run

Hi,
I have a mex function which I am using in a loop. After many iterations matlab gives access violation error and crashes. When I did a little search I found out that it may be resulting from memory allocation. Is there any way to define inputs and outputs differently that I will not get this crash problem? Or should I search for the solution somewhere else in the c code?
Thank you.
Ezgi Köker
void mexFunction(int nlhs, mxArray *plhs[], int nrhs,
const mxArray *prhs[])
{
double *altsin, *ustsin,
*altkis, *ustkis,
*xx, *xi, *fonk,
*afr, *mrg, *y, *x, *qs, lo;
long *ndeg, *lver,
*gedeg, edeg, ferti, kac,
nx, ny, nyi, amac;
int a, b;
int sonuc;
int carpan=0,i;
/* Defining inputs */
nx = mxGetScalar(prhs[0]);
ny = mxGetScalar(prhs[1]);
nyi = mxGetScalar(prhs[2]);
amac = mxGetScalar(prhs[3]);
ndeg = mxGetData(prhs[4]);
altsin = mxGetPr(prhs[5]);
ustsin = mxGetPr(prhs[6]);
altkis = mxGetPr(prhs[7]);
ustkis = mxGetPr(prhs[8]);
xi = mxGetPr(prhs[9]);
lo = mxGetScalar(prhs[10]);
a = (int)nvars_in+1;
b = (int)nfun_in+1;
/* Defining outputs */
plhs[0] = mxCreateDoubleMatrix(1,a, mxREAL);
xx = mxGetPr(plhs[0]);
plhs[1] = mxCreateDoubleMatrix(1,b, mxREAL);
fonk = mxGetPr(plhs[1]);
plhs[2] = mxCreateDoubleMatrix(1,b, mxREAL);
afr = mxGetPr(plhs[2]);
plhs[3] = mxCreateDoubleMatrix(1,b, mxREAL);
mrg = mxGetPr(plhs[3]);
plhs[4] = mxCreateNumericMatrix(1,a, mxUINT32_CLASS, mxREAL);
lver = mxGetData(plhs[4]);
plhs[5] =mxCreateNumericMatrix(1,b, mxUINT32_CLASS, mxREAL);
gedeg = mxGetData(plhs[5]);
plhs[6] =mxCreateDoubleMatrix(1,1, mxREAL);
qs = mxGetPr(plhs[6]);
sevket( nx, ny, nyi, amac,
ndeg, altsin, ustsin, altkis, ustkis,
xx, xi, fonk, mrg, lver,
redgr, gedeg, edeg, ferti, kac,
carpan, sonuc, sonuc, a, b, qs, lo);
}

 Accepted Answer

Jan
Jan on 20 Jun 2017
Edited: Jan on 20 Jun 2017
Do not use a long to catch the output of mxGetScalar, which replies a double. int is not a good choice also for a and b, when the documentation explains clearly, that mxCreateDoubleMatrix expects an mwSize.
It is much safer to specify the wanted data type directly using int64_T or mwSize, size_t etc. Letting the compiler decide which data type to use4, is a fragile method. E.g.:
long *ndeg
ndeg = mxGetData(prhs[4]);
If prhs[4] is a int32, use:
int32_T *ndeg
if (!mxIsInt32(prhs[4])) {
mexErrMsgIdAndTxt("YourFunc:BadInput:In5", "5th input must be an INT32");
}
ndeg = (int32_T *) mxGetData(prhs[4]);
But I guess boldly, that the problem is hidden inside sevget. Perhaps you access unallocated memory. Start with cleaning the types and then test the code again exhaustively.

More Answers (3)

ezgi koker
ezgi koker on 22 Jun 2017
Thank you for the answer. The problem is that my main function contains a part which is written by someone else so I can not change the defined data types. nx, ny, nyi and amac are defined as long type but when I try to get them by using (int32_T *)mxGetData(prhs[0]), Matlab crashes at the first run. And for the outputs, does this matrix creating part: plhs[1] = mxCreateDoubleMatrix(1,b, mxREAL); may cause a memory problem? Is there a way that I can change how I get the outputs? Or should I free the memory for the inputs after I call the main code?

1 Comment

You can still import the data in the exact type they are store in Matlab at first and convert them in the next step:
int32_T *nxI; % This is a pointer!
long nx;
nxI = (int32_T *)mxGetData(prhs[0]);
nx = (long) *nxI;
While:
plhs[1] = mxCreateDoubleMatrix(1,b, mxREAL);
fonk = mxGetPr(plhs[1]);
is fine, when you do not access more than fonk[b-1], this is suspicious:
plhs[4] = mxCreateNumericMatrix(1,a, mxUINT32_CLASS, mxREAL);
lver = mxGetData(plhs[4]);
A long is defined as:
Long signed integer type. Capable of containing at least the
[2,147,483,647, +2,147,483,647] range;
at least! It can be a 64 bit integer also and then the code can crash. It depends on the compiler, what an "int" or "long" is, but in Matlab an int32 has the type int32_T on all Matlab versions, operating systems and processors. Do not mix the flexible and fixed definitions, because this causes troubles very often and reliably.
Even if te part is written by someone else, it is currently crashing and you cannot trust the results if if it ran without a crash. The code needs a re-design.

Sign in to comment.

ezgi koker
ezgi koker on 29 Jun 2017
I understand the problem now. I get the input with double type from matlab and convert to long in the c code. It worked fine with nx, ny, nyi and amac which are all single scalars but now I have problem with converting long type matrixes. I took the matrix ndeg from matlab as a double matrix (ndegp) but while converting I tried: for( i=0; i<21; i++ ) { ndeg[i] = (long)ndegp[i]; }
and this did not work. Is there any way I can do it?

1 Comment

Please post the code. How did you allocate the ndeg array? mxAlloc?

Sign in to comment.

ezgi koker
ezgi koker on 2 Jul 2017
Edited: Jan on 4 Jul 2017
The code is a little bit long but I write below the parts that I have added to the code. There are two additional functions which are called inside the main function and there are "long" variables inside them. So I try to convert them also to be able to make the data transfer easily from Matlab. But now I can not make it work even for one run. Also I know the program is working but Matlab crashes and don't give me the results.
For the outputs which are defined as "long" in the code, I am now trying to convert their definition to "double" but I couldn't make it yet. At first I tried converting them to double at the end of the main code(sevket) but it didn't work.
int sevket(long nx, long ny, long nyi, long amac, long ndeg[],double altsin[],
double ustsin[], double altkis[], double ustkis [],double xx [],
double xi[],double fonk[],double afr[],double mrg[], long lver[],
long gedeg[],long edeg, long ferti, long kac, int carpan, int sonuc, int a,
int b, double qs[], double lo[], double ndegp[]);
{
int i;
for (i=0; i<a; i=i++){
xx[i] = xi[i];
}
for( i=0; i<a; i++ ) {
ndeg[i] = (long)ndegp[i];
}
.
.
Some calculations
.
.
void func_1(double f[], double x[], int a, int b, double lo[])
{
mxArray *rhs[2], *lhs[1];
double *xp, *fp, *lop;
int i;
rhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
lop = mxGetPr(rhs[0]);
for( i=0; i<1; i++ ) {
lop[i] = lo[i];
}
rhs[1] = mxCreateDoubleMatrix(a,1,mxREAL);
xp = mxGetPr(rhs[1]);
for( i=0; i<a; i++ ) {
xp[i] = x[i];
}
mexCallMATLAB( 1, lhs, 2, rhs, "functions" );
mxDestroyArray(rhs[0]);
mxDestroyArray(rhs[1]);
if( lhs[0] ) {
fp = mxGetPr(lhs[0]);
for( i=0; i<b; i++ ) {
f[i] = fp[i];
}
mxDestroyArray(lhs[0]);
}
return;
} /* end of function_1 */
void func_2(double x[], long n, double kal[], long satir[],
long kolon[], long *nz, int a, double lo[])
{
mxArray *rhs[2], *lhs[4];
double *xp, *kalp, *lop, *satirp, *kolonp, *nzp;
int i;
rhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
lop = mxGetPr(rhs[0]);
for( i=0; i<1; i++ ) {
lop[i] = lo[i];
}
rhs[1] = mxCreateDoubleMatrix(a,1,mxREAL);
xp = mxGetPr(rhs[1]);
for( i=0; i<a; i++ ) {
xp[i] = x[i];
}
mexCallMATLAB( 4, lhs, 2, rhs, "function_2" );
mxDestroyArray(rhs[0]);
mxDestroyArray(rhs[1]);
if( lhs[0] ) {
kalp = mxGetPr(lhs[0]);
for( i=0; i<41; i++ ) {
kal[i] = kalp[i];
}
mxDestroyArray(lhs[0]);
}
if( lhs[1] ) {
satirp = mxGetPr(lhs[1]);
for( i=0; i<41; i++ ) {
satir[i] = (long)satirp[i];
}
mxDestroyArray(lhs[1]);
}
if( lhs[2] ) {
kolonp = mxGetPr(lhs[2]);
for( i=0; i<41; i++ ) {
kolon[i] = (long)kolonp[i];
}
mxDestroyArray(lhs[2]);
}
if( lhs[3] ) {
nzp = mxGetPr(lhs[3]);
*nz = (long)nzp[0];
mxDestroyArray(lhs[3]);
}
return;
} /* end of function_2 */
.
.
Some calculations
.
.
void mexFunction(int nlhs, mxArray *plhs[], int nrhs,
const mxArray *prhs[])
{
double *altsin, *ustsin,
*altkis, *ustkis,
*xx, *xi, *fonk,
*afr, *mrg, *y, *x, *qs, *lo, *ndegp;
long *ndeg, *lver,
*gedeg, edeg, ferti, kac,
nx, ny, nyi, amac;
double nxp, nyp, nyip, amacp;
int a, b;
int sonuc;
int carpan=0,i;
/* Defining inputs */
nxp = mxGetScalar(prhs[0]);
nyp = mxGetScalar(prhs[1]);
nyip = mxGetScalar(prhs[2]);
amacp = mxGetScalar(prhs[3]);
nx = (long) nxp;
ny = (long) nyp;
nyi = (long) nyip;
amac = (long) amacp;
ndeg = mxGetPr(prhs[4]);
altsin = mxGetPr(prhs[5]);
ustsin = mxGetPr(prhs[6]);
altkis = mxGetPr(prhs[7]);
ustkis = mxGetPr(prhs[8]);
xi = mxGetPr(prhs[9]);
lo = mxGetPr (prhs[10]);
a = (int)nx+1;
b = (int)ny+1;
/* Defining outputs */
plhs[0] = mxCreateDoubleMatrix(1,a, mxREAL);
xx = mxGetPr(plhs[0]);
plhs[1] = mxCreateDoubleMatrix(1,b, mxREAL);
fonk = mxGetPr(plhs[1]);
plhs[2] = mxCreateDoubleMatrix(1,b, mxREAL);
afr = mxGetPr(plhs[2]);
plhs[3] = mxCreateDoubleMatrix(1,b, mxREAL);
mrg = mxGetPr(plhs[3]);
plhs[4] = mxCreateNumericMatrix(1,a, mxUINT32_CLASS, mxREAL);
lver = mxGetData(plhs[4]);
plhs[5] =mxCreateNumericMatrix(1,b, mxUINT32_CLASS, mxREAL);
gedeg = mxGetData(plhs[5]);
plhs[6] =mxCreateDoubleMatrix(1,1, mxREAL);
qs = mxGetPr(plhs[6]);
sevket( nx, ny, nyi, amac,
ndeg, altsin, ustsin, altkis, ustkis,
xx, xi, fonk, afr, mrg, lver,
gedeg, edeg, ferti, kac,
carpan, sonuc, sonuc, a, b, qs, lo, ndegp);

2 Comments

I couldn't manage to correct the format for better view. If you like I can add it as a separate file.
Jan
Jan on 4 Jul 2017
Edited: Jan on 4 Jul 2017
@ezgi koker: You could not format the code properly? I've done this for you this time: I've selected the code with the mouse and hit the "{} Code" button. This has been explained thousands of times in the forum, see e.g. How to use Markup.
This is the section for answers. It would be more useful to add all information required for understanding the problem in the section for the question. Leave it here this time, and for questions in the future, please care for posting all relevant details in the question, e.g. by appending new details marked by "[EDITED]".
You code still contains:
long *ndeg;
ndeg = mxGetPr(prhs[4]);
As I've mentioned already, this will drive you into troubles, because mexGetPr replies a pointer to a double array. You cannot be sure, that you long array uses the same number of bits. If long is a 32 bit integers, this code must crash. Don't do this. It is not clear, which type the 5th input has, but if it is a double, use:
double *ndeg_d;
long *ndeg;
int i, n_ndeg;
ndeg_d = mxGetPr(prhs[4]);
n_ndeg = (int) mxGetNumberOfElements(prhs[4]);
ndeg = mxAlloc(n_ndeg * sizeof(long));
for (i = 0; i < n_ndeg; i++) {
ndeg[i] = (long) ndeg_d[i];
}
Note that such data copies and conversion will take a lot of time. For efficient code, this should be avoided. The clean and fast solution would to compile the code such, that it accepts the data types provided by Matlab, and not to convert the data twice.
Another example for the cofusion of types:
long *gedeg;
plhs[5] = mxCreateNumericMatrix(1,b, mxUINT32_CLASS, mxREAL);
gedeg = mxGetData(plhs[5]); % mxGetData replies a void *
inside sevket gedeg is used as array of type long. Are you sure, that long is a UINT32?
I prophesize that your code will crash until you fixed it using the reliably defined data types int32_T and so on instead of long. Even if you can manage the code to run on your computer, it might fail with a new compiler or on a different machine.
C is fragile and you see that mixing the fixed defined Matlab classes and the compiler dependent types like long and int let the code crash. In all other threads concerning these problems in Mex functions, using the strictly defined classes like uint32_T fixed the problems immediately. Therefore I consider this as the best, most reliable and efficient solution and suggest it again. It will be much easier to adjust the code of sevket, than to struggle with the inconsistencies of calling the function.

Sign in to comment.

Categories

Products

Asked:

on 20 Jun 2017

Edited:

Jan
on 4 Jul 2017

Community Treasure Hunt

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

Start Hunting!