Memory leak in a c++ mex file. Need to spot the memory leak and resolve it.

Hey all. I have been given a (MEX)C++ code to use for an optimization task. I have worked on programming and MEXing FORTRAN codes before, but MEXing C++ is kind new to me especially that I noticed memory leak is a huge issue when I am looping over the MEX file in optimization iterations. It keep eating the memory until MATLAB gives an error and I have to do clear all to free up the memory.
I tried spotting and resolving the spot(s) that memory is leaking but have had no luck. I am by no means an expert in MEXing and memory management so I would like to get some help here from the community experts. Any help that points me toward the right direction will be much appreciated.
Here is my mexFunction:
void mexFunction(int nlhs, const mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// Function arguments
// t, DT, DP
double t, DT;
// Declare the local structure
structD *DP;
t = *mxGetPr( prhs[0] );
DT = *mxGetPr( prhs[1] );
// Get the root structure that contains the Array and tables
const mxArray *mxDP = prhs[2];
// Get the array structure
const mxArray *mxDPArray = mxGetField( mxDP, 0, (const char *)"DPArray" );
// Convert the array structure to a double array so we can access it directly
double *DPArray = mxGetPr( mxDPArray );
// Now convert the entire structure to the C++ structure.
DP = BuildDP( mxDP );
// Calculate the F values given the inputs
double valuesF = myFunF( t, DT, DP );
// move the DP structure changes back into the F value
DP2F( DP, DPArray, valuesF );
// Return the array with it's changed values
plhs[0] = mxDuplicateArray( mxDPArray );
}
Obviously, there are a couple of other functions called here. I can provide those as well, but I thought it would be better to not make it a long piece of code and stick with the main function.

4 comentarios

There is no memory leaking going on in the code you have posted thus far. So it must be happening in code that you haven't shown us yet (i.e., inside the BuildDP or myFunF or DP2F functions). If a "clear all" statement fixes things, then I would suspect the memory may be buried inside a C++ class variable of some sort. But impossible to say without seeing the code, and without knowing how you are calling this mex routine.
Also, it appears that your code may be doing in-place calculations on one of the input variables based on the comments and that last line of code. This can have unwanted side effects unless you really know what you are doing.
Thanks James for your quick comment. I managed to resolve this issue (well, a colleague helped me and all credit goes to him). You are right, it was not anything in this function that was causing the memory leak. It was the DP variable that was created in BuildDP function. Basically every time that BuildDP was called, structDamper *DP = new structD; was run and that by itself kept eating the memory. A quick dirty solution that I did was I put delete DP; at the end and it did the job for me.
That being said, I would like to know your thoughts on using delete and also, the side effects of in-place calculations you mentioned.
Thanks again for sharing your thoughts.
Using new and delete is fine, but has the potential risk of a memory leak if the mex routine encounters an error of some sort and returns control back to the caller in between the new and the delete. If it is simple arrays or structs your are allocating, you might consider changing these to using mxMalloc and mxFree (assuming structDamper is just a simple struct of course). That way this memory will be on the garbage collection list and will have no risk of leaking. But if there is no potential for the mex routine to error in between the new and the delete, then I probably wouldn't bother with this.
As for the in-place stuff, here is why I made that remark. mxDPArray is an mxArray that came from a field of prhs[2], an input (i.e., mxGetField points directly at a part of the input variable prhs[2] ... not at a copy). But that last comment in your code says "Return the array with it's changed values", returning a copy of mxDPArray. This would indicate that your code is changing the values inside prhs[2] (presumably the double data of mxDPArray which is a field element of prhs[2] but this code isn't shown so I can't tell for sure). In fact, your code would not make much sense unless this is in fact happening. The danger is that changing an input variable in-place will simultaneously change any variable in the caller workspace that is sharing this variable (shared data copy or reference data copy). You can get away with this in some circumstances, but it can bite you in other circumstances. Now, maybe it is your intention to modify prhs[2] in-place and you are well aware of this. But maybe not, hence my remark.
The standard approach is to duplicate the array at the beginning, and then modify this duplicate. I.e., the outline of the code would look something like the following instead. Note that plhs[0] is created up front, and all data manipulation of the doubles happens on the data of plhs[0], not in-place on the data of one of the input variables.
// Get the root structure that contains the Array and tables
const mxArray *mxDP = prhs[2];
// Get the array structure
const mxArray *mxDPArray = mxGetField( mxDP, 0, (const char *)"DPArray" );
// Create the array to return
plhs[0] = mxDuplicateArray( mxDPArray );
// Convert the array structure to a double array so we can access it directly
double *DPArray = mxGetPr( plhs[0] );
// Now convert the entire structure to the C++ structure.
DP = BuildDP( mxDP );
// Calculate the F values given the inputs
double valuesF = myFunF( t, DT, DP );
// move the DP structure changes back into the F value
DP2F( DP, DPArray, valuesF );
What you say totally makes sense. As I said, I did not write this code. I was responsible to use the compiled version of this c-mex code in an optimization algorithm where I found there is a huge memory leak. Then I asked for the source code to figure out what was causing it. Anyways, what you pointed out, although was not my main question, but I think would have potentially affected the performance of the optimization algorithm I am implementing.
Thanks a lot buddy.

Iniciar sesión para comentar.

Respuestas (0)

Categorías

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

Preguntada:

el 24 de Mzo. de 2017

Comentada:

el 24 de Mzo. de 2017

Community Treasure Hunt

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

Start Hunting!

Translated by