From: James Tursa on
"James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <i39p3b$975$1(a)fred.mathworks.com>...
> "Balint Takacs" <b.takacs(a)imperial.ac.uk> wrote in message <i39m02$jou$1(a)fred.mathworks.com>...
> > Does anybody know whether mxGetCell() allocates memory, that is, its output mxArray* should be released by mxDestroy() after its use?
> >
> > The documentation says that it is possible that the function fails because 'Insufficient free heap space to hold the returned cell mxArray'. However, it looks a bit weird and inefficient that a deep copy of the cell element is made upon simply accessing it.
>
> mxGetCell returns the pointer to the original mxArray in the cell, it does *not* allocate memory and create a deep copy of the cell contents. You can verify this with the following mex file:
>
> // cellpr.c
> // input is a cell array, prints the address of the first cell
> // no output
> #include "mex.h"
> void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
> {
> mxArray **p;
> p = mxGetData(prhs[0]);
> mexPrintf("Raw 1st cell address = %p\n",*p);
> mexPrintf("mxGetCell 1st address = %p\n",mxGetCell(prhs[0],0));
> }
>
> >> mex cellpr.c
> >> c = {1.23}
> c =
> [1.2300]
> >> cellpr(c)
> Raw 1st cell address = 0B15D0A0
> mxGetCell 1st address = 0B15D0A0
>
> You can see that the raw mxArray * address contained in the data area of the cell input prhs[0] is exactly the same as the address returned by the mxGetCell call. No copy is made. The warning in the doc about insufficient heap space causing a failure is probably wrong ... I have no idea why this function would be using any heap space. Same comment would hold for mxGetField and mxGetFieldByNumber for structures. The new mxGetProperty, on the other hand, *does* return a deep copy of the property mxArray and thus uses allocated memory from the heap.

I never answered your question directly. The answer, generally, is no, you should not use mxDestroyArray on the result of a mxGetCell call (or mxGetField or mxGetFieldByNumber call). You *should* use mxDestroyArray on the result of a mxGetProperty call. The only reason one would deviate from this is if you are building a cell array from scratch inside your mex routine and you want to change the contents of one of the cells. Since the cell array is not part of the workspace and is not sharing with any other variables you could destroy a cell and then NULL out the pointer. e.g.,

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mxArray *mx, *mycell;
mx = mxGetCell(prhs[0],0);
// do some stuff with mx
mxDestroyArray(mx); // <-- BAD, probably cause MATLAB crash!
//
mycell = mxCreateCellMatrix(1,1);
mx = mxCreateDoubleScalar(1.23);
mxSetCell(mycell, 0, mx);
// use mycell for something
mxDestroyArray(mx);
mxSetCell(mycell, 0, NULL); // <-- If you destroy it, then you must NULL the cell
mx = mxCreateDoubleScalar(4.56);
mxSetCell(mycell, 0, mx);
// use mycell for something else
mxDestroyArray(mycell); // does a deep destruction, so no need to destroy cell individually
}


James Tursa