Memory leak with matlab file creation??

Hi All, I use MATLAB 2010a and Visual2010 to create a DLL lib(I use Matrix Library API).
My problem is : when I'm tring to run my DLL throw matlab(many times), matlab display a memory error.
I suggest to post my pseudo-code of the Creation/Destruction of the matlab struct.
Create :
MainArray = mxCreateStructMatrix(1,1,0,NULL);
mxAddField(MainArray,"Field1");
mxAddField(MainArray,"Field2");
mxAddField(MainArray,"Field3");
PtrArrayField1 = mxCreateStructMatrix(1,1,0,NULL);
PtrArrayField2 = mxCreateString("Field2");
PtrArrayField3 = mxCreateNumericArray(C_NDIMS,MxDim,mxUINT32_CLASS,mxREAL);
PtrArrayTmp = mxGetField(MainArray,0,"Field2");
mxDestroyArray(PtrArrayTmp);
PtrArrayTmp = NULL;
mxSetField(MainArray,0,"Field2",PtrArrayField2);
PtrArrayTmp = mxGetField(MainArray,0,"Field3");
mxDestroyArray(PtrArrayTmp);
PtrArrayTmp = NULL;
mxSetField(MainArray,0,"Field3",PtrArrayField3);
mxAddField(PtrArrayField1 ,"SubField1");
mxAddField(PtrArrayField1 ,"SubField2");
mxAddField(PtrArrayField1 ,"SubField3");
PtrArraySubField1 = mxCreateString("SubField1");
PtrArraySubField2 = mxCreateString("SubField2");
PtrArraySubField3 = mxCreateString("SubField3");
PtrArrayTmp = mxGetField(PtrArrayField1,0,"SubField1");
mxDestroyArray(PtrArrayTmp);
PtrArrayTmp = NULL;
PtrArrayTmp = mxGetField(PtrArrayField1,0,"SubField2");
mxDestroyArray(PtrArrayTmp);
PtrArrayTmp = NULL;
PtrArrayTmp = mxGetField(PtrArrayField1,0,"SubField3");
mxDestroyArray(PtrArrayTmp);
PtrArrayTmp = NULL;
mxSetField(PtrArrayField1,0,"SubField1",PtrArraySubField1);
mxSetField(PtrArrayField1,0,"SubField2",PtrArraySubField2);
mxSetField(PtrArrayField1,0,"SubField3",PtrArraySubField3);
PtrArrayTmp = mxGetField(MainArray,0,"Field1");
mxDestroyArray(PtrArrayTmp);
PtrArrayTmp = NULL;
mxSetField(MainArray,0,"Field1",PtrArrayField1);
///////////////////////////////////////////////////////// /*End Creation*/ /////////////////////////////////////////////////////////
Destroy :
PtrArrayField = mxGetField(MainArray,0,"Field2");
mxSetField(MainArray,0,"Field2",NULL);
mxDestroyArray(PtrArrayField);
PtrArrayField = NULL;
PtrArrayField = mxGetField(MainArray,0,"Field3");
mxSetField(MainArray,0,"Field3",NULL);
mxDestroyArray(PtrArrayField);
PtrArrayField = NULL;
PtrArrayField = mxGetField(MainArray,0,"Field1");
PtrArraySubField = mxGetField(PtrArrayField,0,"SubField1");
mxSetField(PtrArrayField,0,"SubField1",NULL);
mxDestroyArray(PtrArraySubField);
PtrArraySubField = NULL;
PtrArraySubField = mxGetField(PtrArrayField,0,"SubField2");
mxSetField(PtrArrayField,0,"SubField2",NULL);
mxDestroyArray(PtrArraySubField);
PtrArraySubField = NULL;
PtrArraySubField = mxGetField(PtrArrayField,0,"SubField3");
mxSetField(PtrArrayField,0,"SubField3",NULL);
mxDestroyArray(PtrArraySubField);
PtrArraySubField = NULL;
mxSetField(MainArray,0,"Field1",NULL);
mxDestroyArray(PtrArrayField);
PtrArrayField = NULL;
///////////////////////////////////////////////////////// /*End Destroy*/ /////////////////////////////////////////////////////////
thank you for your help.

Answers (1)

Abdellatif - for every mxCreate... that creates an mxArray you need to call mxDestroyArray on that array. You will need to rework your code so that you always pair up a create with a destroy (once finished with the array that was allocated memory via the create function).

10 Comments

Geoff, thanks for your quick answer.
Yes, i am totally agree with you, and i think thant my pseudo-code respect your rule. In reality my code is more complicated than the pseudo-code: In my code, I have to use mxAddField after creating an empty struct.
According to your knowledge, could my pseudo-code generate a memory leak? and if you think that my way(to create a mat file)is dirty, could you please help me by suggesting the right way.
Thanks for your help.
Take a look at
PtrArrayField2 = mxCreateString("Field2");
Where do you free the memory allocated to PtrArrayField2? Same with
MainArray = mxCreateStructMatrix(1,1,0,NULL);
There is no corresponding line in your pseudocode that indicates that you are freeing memory that was allocated to this mxArray structure.
For the MainArray, I'm agree with you.
But for the PtrArrayField2, I think that the following pseudo-code destroy the allocated memory :
PtrArrayField = mxGetField(MainArray,0,"Field2");
mxSetField(MainArray,0,"Field2",NULL);
mxDestroyArray(PtrArrayField);
PtrArrayField = NULL;
How? PtrArrayField is not PtrArrayField2..
I think it's the same, because it represente the ptrArray of the field2.
I don't think it is the same. Note that you do the following
PtrArrayField1 = mxCreateStructMatrix(1,1,0,NULL);
PtrArrayField2 = mxCreateString("Field2");
PtrArrayField3 = mxCreateNumericArray(C_NDIMS,MxDim,mxUINT32_CLASS,mxREAL);
So you create three different mxArrays, but at no time do you free memory for any. And PtrArrayField is just a field returned by mxGetField. Now note the comment from mxGetField:
Do not call mxDestroyArray on an mxArray returned by the mxGetField function.
Destroy calls should only be paired with create function calls.
After calling the code mxSetField(MainArray,0,"Field2",PtrArrayField2); the function mxGetField returns the value of PtrArrayField2. So, i think that there is no-problem of not freed memory.
The code (which you haven't posted) may do that, but the pseudo-code does not. And from the MATLAB documentation, you are not supposed to be calling mxDestroyArray on an mxArray returned by the mxGetField function...which is exactly what your pseudo-code is showing.
You are right, But according to the documentation of mxSetField : Use the mxGetField function to get a pointer to the field, call mxDestroyArray on the pointer, then call mxSetField to assign the new value. and this is what i am doing in my pseudo-code:
for the struct creation :
PtrArrayField2 = mxCreateString("Field2");
PtrArrayTmp = mxGetField(MainArray,0,"Field2");
mxDestroyArray(PtrArrayTmp);
PtrArrayTmp = NULL;
mxSetField(MainArray,0,"Field2",PtrArrayField2);
for the struct destruction:
PtrArrayField = mxGetField(MainArray,0,"Field2");
mxSetField(MainArray,0,"Field2",NULL);
mxDestroyArray(PtrArrayField);
PtrArrayField = NULL;
That pseudo-code seems a little complicated, especially for the struct destruction. Reviewing the documentation indicates that you would only do what you have shown (above) for changing the field. For the other, To free memory for structures created using this function, call mxDestroyArray only on the structure array. Do not call mxDestroyArray on the array pvalue points to. If you do, MATLAB® attempts to free the same memory twice, which can corrupt memory.
I think then that you could do something like the following
#include "mex.h"
#include <string.h>
#define NUMBER_OF_STRUCTS 1
#define NUMBER_OF_FIELDS 1
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
const char* pFieldNames[] = {"Field2"};
mwSize dims[2] = {1, NUMBER_OF_STRUCTS};
// create the struct array
mxArray* pStructArray = mxCreateStructArray(2,dims,
NUMBER_OF_FIELDS, pFieldNames);
// create the field value
mxArray* pArrayField2 = mxCreateString("this is my string value");
// set the field
mxSetField(pStructArray,0,"Field2",pArrayField2);
// do modification
// free memory allocated to current value
mxDestroyArray(pArrayField2);
// create the new string value
pArrayField2 = mxCreateString("this is my other string value");
// update the field
mxSetField(pStructArray,0,"Field2",pArrayField2);
// free memory from struct
mxDestroyArray(pStructArray);
}

Sign in to comment.

Categories

Asked:

on 13 Oct 2014

Edited:

on 17 Oct 2014

Community Treasure Hunt

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

Start Hunting!