Calling mxFree crashes MATLAB if data is associated with mxArray.

1 view (last 30 days)
I can dynamically allocate memory and free it without an issue. If I associate the data with an mxArray* it throws an exception when I try to free it. For example, this works fine:
double *a;
a = (double*) mxMalloc(sizeof(double));
mxFree(a);
But this throws an exception:
mxArray *A;
double *a;
A = mxCreateDoubleMatrix(0, 0, mxREAL);
a = (double*) mxMalloc(sizeof(double));
mxSetData(A, a);
mxFree(a);
Setting the size of A with mxSetM() and mxSetN() still throws an exception. I am doing this because I'd like to keep reallocating memory of varying size inside of a FOR loop without having to keep re-declaring the mxArray variable.
Probably I am just misunderstanding how this is supposed to be done, but I'd appreciate if someone could clarify.
Jason

Answers (1)

James Tursa
James Tursa on 3 Jul 2014
Edited: James Tursa on 3 Jul 2014
When you do the following:
mxSetData(A, a);
what happens is the address contained in "a" is now part of the mxArray "A". Whenever "A" is subsequently destroyed, the MATLAB Memory Manager will also automatically free the data area as well. In your case, since you have already free'd the address contained in "a", you have invalidated the mxArray "A" so when it free's the data area it will end up trying to free the same memory that was already free'd. That will end up in a crash.
Rule: If you attach a memory block to an mxArray via mxSetData, mxSetImagData, mxSetPr, mxSetPi, mxSetIr, mxSetJc, then DO NOT manually free it. It's disposition will subsequently depend on the disposition of the mxArray it is a part of.
E.g., this would not crash:
mxArray *A;
double *a;
A = mxCreateDoubleMatrix(0, 0, mxREAL);
// Start of loop
a = (double*) mxMalloc(sizeof(double));
mxSetData(A, a);
// Then do whatever you want with "A"
mxSetData(A, NULL); % Disassociate memory pointed to by "a" from "A"
mxFree(a);
// Then go back to start of loop
mxDestroyArray(A); // After loop is done, destroy "A"
  2 Comments
Jason Pacheco
Jason Pacheco on 3 Jul 2014
Thanks, this makes sense. Alternatively, I think I could just iterate the following inside of the loop:
A = mxCreateDoubleMatrix(0, 0, mxREAL);
a = (double*) mxMalloc(sizeof(double));
mxSetData(A, a);
// Do stuff with A
mxDestroyArray(A);
This doesn't require manually freeing the pointer a and setting A to NULL. It doesn't seem like there should be a memory leak since mxDestroyArray() should free the data, right?
Jason
James Tursa
James Tursa on 3 Jul 2014
Edited: James Tursa on 3 Jul 2014
Correct. What you show will work fine and there will be no memory leak. Basically, if you want to manually free the data memory with mxFree(), then you must set the mxArray data pointer to NULL (or to some other different valid memory block) so that the MATLAB Memory Manager will not try to free the same memory block again downstream. If you leave the memory block attached to the mxArray, then don't manually free it since the MATLAB Memory Manager will do so automatically when the mxArray gets destroyed downstream.
Caveat: All of my comments apply to your specific scenario. If you have the potential for the mxArray to be a shared data copy or reference copy or shared parent copy of another mxArray variable, then the discussion gets quite involved and is beyond the scope of your example.

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!