malloc error when making multiple subsequent calls to mex file

10 visualizaciones (últimos 30 días)
Julien MJ
Julien MJ el 6 de Jul. de 2015
Comentada: Julien MJ el 6 de Jul. de 2015
I wrote a mex file in C to simulate lattice dynamics. I can call the mex function once without any errors. However, when I make a subsequent calls to the function I get the following malloc error and matlab crashes:
MATLAB_maci64(1722,0x10ea01000) malloc: *** error for object 0x6000001c0940: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug (lldb)
Sometimes the error occurs on the second call, but it will often take a couple more calls. I tried using a malloc_error_break breaking point while debugging with Xcode but it doesn't catch on anything. I posted my (awful-looking) C code bellow.
Should I be freeing memory at one point in the mex function?
I am a beginner in both C and Matlab code, so I don't have a very good understanding of memory management, especially for mex functions.
Thank you for your time,
Best,
Julien
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <matrix.h>
#include <mex.h>
//Computation function
void Lat_dynam(const int N_l,
const int R_l,
const int det_k_l,
double *Bed_init_l,
double *Bed_out_l,
double *Det_out_l,
double *Rel_out_l,
const double pStabil_l,
const double pRecover_l,
const double pDisturb_l,
const double pDist_ini_l,
const double rho_l,
const int det_effect_l)
{
//Declare local variables not received as input
mwSize i, j, l, k, n, update, step, seed;
int m, d, o;
double n_Occ, n_Dist, pDisturb_real, r;
//Disturbance/recovery operations on random cells
seed = 1456739853;
srand48(seed);
m = (int)(drand48()*(N_l*N_l));
for (i=0; i<(int)(N_l*N_l); i++){
Bed_out_l[i] = Bed_init_l[i];
}
for (step=1; step<(int)(R_l+1); step++){
for (update=1; update<(int)(2); update++){
//Compute neighborhoods
d = 0;
o = 0;
//select random lattice cell
if (Bed_out_l[m+(step-1)*N_l*N_l]!=0) {
//Neighbourhood assessment with periodic boundary conditions
for (j=(m-N_l); j<(int)(m+N_l+2); j=j+N_l){ //Navigate columns
if (j<((step-1)*N_l*N_l)){
j=step*(N_l*N_l)-N_l+m;
}
else if (j>=(step*N_l*N_l)){
j=((step-1)*N_l*N_l)+(N_l-(N_l*N_l)-m);
}
for (l=j-1; l<(int)(j+2); l++){ //Navigate rows
if (((l+1)%N_l) == 0 && l == (j-1)){
l=l+N_l; //Same row position but on the following column
}
else if (l%N_l == 0 && l == (j+1)){
l=l-N_l; //Same row position but on the previous column
}
if (Bed_out_l[m+(step-1)*N_l*N_l]==0){
if (l==m){
//Do nothing (exclude updated cell from n_Dist calculation)
}
else{
d++;
}
}
else if (Bed_out_l[m+(step-1)*N_l*N_l]==2){
if (l==m){
//Do nothing (exclude updated cell from n_Occ calculation)
}
else{
o++;
}
}
}
}
}
//Neighbourhoods occupancy
n_Dist = d/8; //Note that n_dist is a proportion of the neighbourhood (not like in Fred's article where it is either 0 or 1)
n_Occ = o/8;
//Update lattice cell state
r=drand48(); //generate random number for state transition evaluation
if (Bed_out_l[m+(step-1)*N_l*N_l]==0){
if (r<=(pStabil_l)){
Bed_out_l[m+(step-1)*N_l*N_l]=1; //stabilization of edge of Disturbed cells
}
}
else if (Bed_out_l[m+(step-1)*N_l*N_l]==1){
if (r<=(pRecover_l*n_Occ)){
Bed_out_l[m+(step-1)*N_l*N_l]=2; //recovery of empty cells using pRecover probability
}
}
else{
if (det_effect_l==0){
pDisturb_real=pDisturb_l*n_Dist*k;
}
else if (det_effect_l==1){
pDisturb_real=pDisturb_l*n_Dist*det_k_l*Bed_out_l[m+(step-1)*N_l*N_l];
}
if (r<=(pDisturb_l*n_Dist*k*+pDist_ini_l)){ //Disturbance of occupied cells using pDisturb proability
Bed_out_l[m+(step-1)*N_l*N_l]=0;
Rel_out_l[update+(step-1)*N_l*N_l]=Det_out_l[m+(step-1)*N_l*N_l]; //Store how much det was released
Det_out_l[m+(step-1)*N_l*N_l]=0; //Reset Det to 0 for this cell.
}
else{
Det_out_l[m+(step-1)*N_l*N_l]=Det_out_l[m+(step-1)*N_l*N_l]+rho_l; //Acretion of detritus
}
}
}
//Copy lattice at the end of the updates cycle
for (n=0; n<(int)(N_l*N_l); n++){
Bed_out_l[(step*N_l*N_l)+n] = Bed_out_l[((step-1)*N_l*N_l)+n];
}
}
}
// Gateway (mexFunction) MATLAB uses as an entry point in the program
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
//Declare variables
/*Note: all the following variables are local to the mexFunction,
will receive their values from prhs[#] variables and be passed to Lat_dynam*/
double *Bed_init, *Bed_out_m, *Rel_out_m, *Det_out_m, pRecover, pDisturb, pStabil, rho, pDist_ini, det_k, det_effect;
int N, R;
//Associate scalar variables to the pointer contained in mxArray
N = mxGetScalar(prhs[0]);
R = mxGetScalar(prhs[1]);
det_k = mxGetScalar(prhs[2]);
pRecover = mxGetScalar(prhs[3]);
pDisturb = mxGetScalar(prhs[4]);
pStabil = mxGetScalar(prhs[5]);
pDist_ini = mxGetScalar(prhs[9]);
rho = mxGetScalar(prhs[6]);
Bed_init = mxGetPr(prhs[7]);
det_effect = mxGetScalar(prhs[8]);
//Dimensions of inputed and output matrices Bed_out_m, Det_out_m, and Rel_out_m
mwSize dims[3] = {N,N,R};
mwSize dims_Rel[2] = {R,N};
//Create output matrices
plhs[0] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
plhs[1] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
plhs[2] = mxCreateNumericArray(2, dims_Rel, mxDOUBLE_CLASS, mxREAL);
//Get pointer to real data in output matrices
Bed_out_m = mxGetPr(plhs[0]);
Det_out_m = mxGetPr(plhs[1]);
Rel_out_m = mxGetPr(plhs[2]);
//Run Lat_dynam
Lat_dynam(N,
R,
det_k,
Bed_init,
Bed_out_m,
Det_out_m,
Rel_out_m,
pStabil,
pRecover,
pDisturb,
pDist_ini,
rho,
det_effect);
}
  1 comentario
Julien MJ
Julien MJ el 6 de Jul. de 2015
I should also specify the multiple calls to the mex function are made using the same input values (and the same seed for the PRNG withing the C code).

Iniciar sesión para comentar.

Respuestas (1)

James Tursa
James Tursa el 6 de Jul. de 2015
Editada: James Tursa el 6 de Jul. de 2015
First thing I noticed was these lines:
int dims[3] = {N,N,R};
int dims_Rel[2] = {R,N};
:
plhs[0] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
plhs[1] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
plhs[2] = mxCreateNumericArray(2, dims_Rel, mxDOUBLE_CLASS, mxREAL);
The signature for mxCreateNumericArray calls for a (mwSize *) type as the 2nd argument. On a 64-bit machine this could be 8-byte integers. You are using (int *) however, which may be 4-byte integers on your machine. I would first make this change:
mwSize dims[3] = {N,N,R};
mwSize dims_Rel[2] = {R,N};
Second thing I noticed is that you don't appear to be initializing things properly. E.g., this code:
int dims[3] = {N,N,R};
:
plhs[0] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
:
Bed_out_m = mxGetPr(plhs[0]);
:
Then inside the Lat_dynam function you have:
for (i=0; i<(int)(N_l*N_l); i++){
Bed_out_l[i] = Bed_init_l[i];
}
:
if (Bed_out_l[m+(step-1)*N_l*N_l]!=0) {
So, Bed_out_m points to a NxNxR sized array, but inside the Lat_dynam function you are only initializing the first NxN slice to Bed_init_l, not the entire NxNxR array. I don't know if this is intentional or not.
Also, downstream in the code you use the variable m in your indexing, but m is not set anywhere. So you are using an uninitialized variable (garbage value) in your indexing. This could cause the index to be out of bounds and result in a memory error.
Third thing I noticed is that you are mixing some mwSize and int calculations. mwSize might very well reduce to a size_t type, which is an unsigned integer. So mixing calculations with these might not yield the answer you were expecting because of signed/unsigned conversions going on in the background. I would double check all of your integer calculations to see if this might be a problem.
  7 comentarios
James Tursa
James Tursa el 6 de Jul. de 2015
I don't see any direct use of malloc or free in your code, so I am just guessing as to the cause of the error you are getting (i.e., some generic memory writing error). In particular, I don't see anything obviously wrong with your use of mxCreateNumericArray or mxGetPr.
I did notice, however, that Rel_out_m points to a RxN matrix. But in your code you access it like this:
Rel_out_l[update+(step-1)*N_l*N_l]
So it looks like the indexing used assumes pages of size NxN which doesn't look right based on the allocated size. You might check into this.
Julien MJ
Julien MJ el 6 de Jul. de 2015
Ok, I wanted to double check the code for such mistakes but didn't realize it could induce memory errors. I will do my homeworks and clean-up the code before asking any more questions.
Thanks a lot for the help and tips,
Best,
Julien

Iniciar sesión para comentar.

Categorías

Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by