malloc error when making multiple subsequent calls to mex file

7 views (last 30 days)
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 Comment
Julien MJ
Julien MJ on 6 Jul 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).

Sign in to comment.

Answers (1)

James Tursa
James Tursa on 6 Jul 2015
Edited: James Tursa on 6 Jul 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 Comments
James Tursa
James Tursa on 6 Jul 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 on 6 Jul 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

Sign in to comment.

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!