Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Destroy Array

Subject: Destroy Array

From: Stiphu

Date: 22 Aug, 2011 12:35:10

Message: 1 of 10

I want to return the array defSys->signal->timeValues, which has the length defSys->signal->sigLen_s, into the Matlab workspace. If I call "mxDestroyArray", Matlab crashes. Why?

// Return function values to Matlab
mxArray *prhsApp;
// Return signal values
prhsApp = mxCreateDoubleMatrix(1, defSys->signal->sigLen_s, mxREAL);
mxSetData(prhsApp, defSys->signal->timeValues);
int status = mexPutVariable("caller", "MEX_timeValues", prhsApp);
mxDestroyArray(prhsApp);

Subject: Destroy Array

From: Stiphu

Date: 22 Aug, 2011 12:45:09

Message: 2 of 10

It used to work before (Matlab2010a, I use now 2011a). I made an example (which does the same thing like the code I posted above):

int myData[] = {1, 2, 3};
mxArray *prhsApp;
prhsApp = mxCreateDoubleMatrix(1, 3, mxREAL);
mxSetData(prhsApp, myData);
mexPutVariable("caller", "MEX_timeValues", prhsApp);
mxDestroyArray(prhsApp);

same result, Matlab crashes as soon as I call mxDestroyArray!

Subject: Destroy Array

From: Bruno Luong

Date: 22 Aug, 2011 12:57:09

Message: 3 of 10

You should be able to guess by your self: You are allowed to destroy mxArray that is no longer used. When you return prhsApp to the caller, it's still alive as MEX_timeValues, thus do you must not destroy it.

Bruno

Subject: Destroy Array

From: Bruno Luong

Date: 22 Aug, 2011 13:03:10

Message: 4 of 10

"Stiphu" wrote in message <j2tj0l$4qq$1@newscl01ah.mathworks.com>...
> It used to work before (Matlab2010a, I use now 2011a).

Pure luck. It used to "works" but it's wrong.

Bruno

Subject: Destroy Array

From: James Tursa

Date: 22 Aug, 2011 14:36:08

Message: 5 of 10

"Stiphu" wrote in message <j2tj0l$4qq$1@newscl01ah.mathworks.com>...
> It used to work before (Matlab2010a, I use now 2011a). I made an example (which does the same thing like the code I posted above):
>
> int myData[] = {1, 2, 3};
> mxArray *prhsApp;
> prhsApp = mxCreateDoubleMatrix(1, 3, mxREAL);
> mxSetData(prhsApp, myData);
> mexPutVariable("caller", "MEX_timeValues", prhsApp);
> mxDestroyArray(prhsApp);
>
> same result, Matlab crashes as soon as I call mxDestroyArray!

Both of your examples crash because you are mixing native C memory (local automatic memory or heap allocated memory) into an mxArray variable. You can't do that because when mxDestroyArray is called you will mess up the MATLAB memory manager as it will try to free the memory behind the pointer you used in the mxSetData call. The proper way to do this is to first detach your C memory from the mxArray (NULLl out the data pointer), and then call mxDestroyArray on it. E.g.,

 int myData[] = {1, 2, 3};
 mxArray *prhsApp;
 prhsApp = mxCreateDoubleMatrix(1, 3, mxREAL);
 mxFree(mxGetData(prhsApp)); // Added line to avoid memory leak
 mxSetData(prhsApp, myData);
 mexPutVariable("caller", "MEX_timeValues", prhsApp);\
 mxSetData(prhsApp, NULL); // Added line to detach C native memory
 mxDestroyArray(prhsApp);

Your listed code also has a memory leak since you overwrite the mxArray data pointer without first freeing the memory that it points to. I have added another line to correct that.

The reason you can get away with using the mixed memory mxArray in the mexPutVariable call is because this function creates a deep copy of the mxArray to put into the workspace, so no native C memory is pointed to in the actual variable that gets put in the workspace eve if there is native C memory in the original. Note that this would *not* be true if you tried to return this variable as one of the plhs[ ] array variables. If you were to try that then you would also likely crash MATLAB at some point downstream.

James Tursa

Subject: Destroy Array

From: James Tursa

Date: 22 Aug, 2011 14:39:09

Message: 6 of 10

"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <j2tjn5$7e0$1@newscl01ah.mathworks.com>...
> You should be able to guess by your self: You are allowed to destroy mxArray that is no longer used. When you return prhsApp to the caller, it's still alive as MEX_timeValues, thus do you must not destroy it.
>
> Bruno

The way he is doing this, by using mexPutVariable, puts a deep copy into the workspace. So it is OK to destroy it afterwards (as long as it is a valid mxArray to begin with ... which in his case is not true).

James Tursa

Subject: Destroy Array

From: James Tursa

Date: 22 Aug, 2011 16:43:09

Message: 7 of 10

"Stiphu" wrote in message <j2tj0l$4qq$1@newscl01ah.mathworks.com>...
> It used to work before (Matlab2010a, I use now 2011a). I made an example (which does the same thing like the code I posted above):
>
> int myData[] = {1, 2, 3};
> mxArray *prhsApp;
> prhsApp = mxCreateDoubleMatrix(1, 3, mxREAL);
> mxSetData(prhsApp, myData);
> mexPutVariable("caller", "MEX_timeValues", prhsApp);
> mxDestroyArray(prhsApp);
>
> same result, Matlab crashes as soon as I call mxDestroyArray!

P.S. I just noticed one other problem with your code. myData is int but you create a double class mxArray to point to it, so you are loading up an address into prhsApp that expects 3 * 8 = 24 bytes worth of data, but with an int you are likely only getting 3 * 4 = 12 bytes of data, and not even the same type. So this will either give garbage at the MATLAB level or bomb the program. myData needs to be double, not int.

James Tursa

Subject: Destroy Array

From: Stiphu

Date: 23 Aug, 2011 12:38:08

Message: 8 of 10

"James Tursa" wrote in message <j2tpgo$s86$1@newscl01ah.mathworks.com>...
> "Stiphu" wrote in message <j2tj0l$4qq$1@newscl01ah.mathworks.com>...
> > It used to work before (Matlab2010a, I use now 2011a). I made an example (which does the same thing like the code I posted above):
> >
> > int myData[] = {1, 2, 3};
> > mxArray *prhsApp;
> > prhsApp = mxCreateDoubleMatrix(1, 3, mxREAL);
> > mxSetData(prhsApp, myData);
> > mexPutVariable("caller", "MEX_timeValues", prhsApp);
> > mxDestroyArray(prhsApp);
> >
> > same result, Matlab crashes as soon as I call mxDestroyArray!
>
> Both of your examples crash because you are mixing native C memory (local automatic memory or heap allocated memory) into an mxArray variable. You can't do that because when mxDestroyArray is called you will mess up the MATLAB memory manager as it will try to free the memory behind the pointer you used in the mxSetData call. The proper way to do this is to first detach your C memory from the mxArray (NULLl out the data pointer), and then call mxDestroyArray on it. E.g.,
>
> int myData[] = {1, 2, 3};
> mxArray *prhsApp;
> prhsApp = mxCreateDoubleMatrix(1, 3, mxREAL);
> mxFree(mxGetData(prhsApp)); // Added line to avoid memory leak
> mxSetData(prhsApp, myData);
> mexPutVariable("caller", "MEX_timeValues", prhsApp);\
> mxSetData(prhsApp, NULL); // Added line to detach C native memory
> mxDestroyArray(prhsApp);
>
> Your listed code also has a memory leak since you overwrite the mxArray data pointer without first freeing the memory that it points to. I have added another line to correct that.
>
> The reason you can get away with using the mixed memory mxArray in the mexPutVariable call is because this function creates a deep copy of the mxArray to put into the workspace, so no native C memory is pointed to in the actual variable that gets put in the workspace eve if there is native C memory in the original. Note that this would *not* be true if you tried to return this variable as one of the plhs[ ] array variables. If you were to try that then you would also likely crash MATLAB at some point downstream.
>
> James Tursa

Tnx James, this works perfectly!

Subject: Destroy Array

From: Stiphu

Date: 24 Aug, 2011 13:50:15

Message: 9 of 10

"James Tursa" wrote in message <j2tpgo$s86$1@newscl01ah.mathworks.com>...
> "Stiphu" wrote in message <j2tj0l$4qq$1@newscl01ah.mathworks.com>...
> > It used to work before (Matlab2010a, I use now 2011a). I made an example (which does the same thing like the code I posted above):
> >
> > int myData[] = {1, 2, 3};
> > mxArray *prhsApp;
> > prhsApp = mxCreateDoubleMatrix(1, 3, mxREAL);
> > mxSetData(prhsApp, myData);
> > mexPutVariable("caller", "MEX_timeValues", prhsApp);
> > mxDestroyArray(prhsApp);
> >
> > same result, Matlab crashes as soon as I call mxDestroyArray!
>
> Both of your examples crash because you are mixing native C memory (local automatic memory or heap allocated memory) into an mxArray variable. You can't do that because when mxDestroyArray is called you will mess up the MATLAB memory manager as it will try to free the memory behind the pointer you used in the mxSetData call. The proper way to do this is to first detach your C memory from the mxArray (NULLl out the data pointer), and then call mxDestroyArray on it. E.g.,
>
> int myData[] = {1, 2, 3};
> mxArray *prhsApp;
> prhsApp = mxCreateDoubleMatrix(1, 3, mxREAL);
> mxFree(mxGetData(prhsApp)); // Added line to avoid memory leak
> mxSetData(prhsApp, myData);
> mexPutVariable("caller", "MEX_timeValues", prhsApp);\
> mxSetData(prhsApp, NULL); // Added line to detach C native memory
> mxDestroyArray(prhsApp);
>
> Your listed code also has a memory leak since you overwrite the mxArray data pointer without first freeing the memory that it points to. I have added another line to correct that.
>
> The reason you can get away with using the mixed memory mxArray in the mexPutVariable call is because this function creates a deep copy of the mxArray to put into the workspace, so no native C memory is pointed to in the actual variable that gets put in the workspace eve if there is native C memory in the original. Note that this would *not* be true if you tried to return this variable as one of the plhs[ ] array variables. If you were to try that then you would also likely crash MATLAB at some point downstream.
>
> James Tursa

An excerpt from the Matlab example "mexgettaray.c":

/* Since variable does not yet exist in MATLAB workspace,
           create it and place it in the global workspace. */
array_ptr=mxCreateDoubleMatrix(1,1,mxREAL);
    }
    
    /* Increment both MATLAB and MEX counters by 1 */
    mxGetPr(array_ptr)[0]+=1;
    mex_count=(int)mxGetPr(array_ptr)[0];
    mexPrintf("%s has been called %i time(s)\n", mexFunctionName(), mex_count);
    
    /* Put variable in MATLAB global workspace */
    status=mexPutVariable("global", array_name, array_ptr);
    
    if (status==1){
mexPrintf("Variable %s\n", array_name);
mexErrMsgTxt("Could not put variable in global workspace.\n");
    }
    
    /* Destroy array */
    mxDestroyArray(array_ptr);

There, they don't mention the two lines you added to my code. Why?

Subject: Destroy Array

From: James Tursa

Date: 24 Aug, 2011 14:40:28

Message: 10 of 10

"Stiphu" wrote in message <j32vin$rcr$1@newscl01ah.mathworks.com>...
>
> An excerpt from the Matlab example "mexgettaray.c":
>
> /* Since variable does not yet exist in MATLAB workspace,
> create it and place it in the global workspace. */
> array_ptr=mxCreateDoubleMatrix(1,1,mxREAL);
> }
>
> /* Increment both MATLAB and MEX counters by 1 */
> mxGetPr(array_ptr)[0]+=1;
> mex_count=(int)mxGetPr(array_ptr)[0];
> mexPrintf("%s has been called %i time(s)\n", mexFunctionName(), mex_count);
>
> /* Put variable in MATLAB global workspace */
> status=mexPutVariable("global", array_name, array_ptr);
>
> if (status==1){
> mexPrintf("Variable %s\n", array_name);
> mexErrMsgTxt("Could not put variable in global workspace.\n");
> }
>
> /* Destroy array */
> mxDestroyArray(array_ptr);
>
> There, they don't mention the two lines you added to my code. Why?

Because they are not attaching other memory to the mxArray. Note that in the above example they create a variable with mxCreateDoubleMatrix, then access its data area directly with the mxGetPr call. Since they never try to *replace* the data pointer via a mxSetPr call (like you do) there is no memory leak and there is nothing that needs to get detached before the mxArray gets destroyed.

James Tursa

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us