MEX-files are loaded into memory the first time they’re called. At this point, global variables in the MEX-file get a location in memory and are initialized. Next mexFunction
is called, where your code gets a chance to allocate memory and assign the pointer to this global variable.
The next time you call the MEX-file, it is still loaded in memory, and those global variables are still there. This time MATLAB just needs to call mexFunction
.
When you do clear mex
or clear all
in MATLAB, the MEX-file will be unloaded from memory. The global variables will stop existing at this point. Because you used mxCalloc
to allocate memory, MATLAB can reclaim the lost memory. If you had used calloc
instead, you would have leaked memory at this point. You no longer have a pointer to the allocated memory, so you have leaked memory at this point (see James' answer below).
The next time you call the MEX-file, it will be like the first time you called it.
Note that, since a MEX-file is a compiled binary, your variable names are no longer visible (except in debug information). The machine code just deals with memory addresses and registers.
In the case of C++, scoping rules, inheritance, etc are all just abstractions that lead to the same machine code you can obtain with C or any other compiled language.
A few cases to clarify things:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
static int* myVar = NULL; // This is basically the same as a global myVar in this case
if(myVar == NULL)
{
myVar = (int*)mxCalloc(sizeof(int*), 10);
//mexMakeMemoryPersistent(myVar); // Let's leave out this line!
myVar[0] = 1;
}
myVar[0] *= 2;
}
In the case above, we didn't make the memory persistent. The myVar
pointer is preserved across MEX-file calls, but not the memory pointed to. The 2nd time you call the MEX-file, myVar[0] *= 2
will do something illegal and likely crash MATLAB.
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int* myVar = NULL; // This is now a local variable
if(myVar == NULL)
{
myVar = (int*)mxCalloc(sizeof(int*), 10);
mexMakeMemoryPersistent(myVar);
myVar[0] = 1;
}
myVar[0] *= 2;
}
In the case above, myVar
will be NULL every time the MEX-file is called, so every time new memory will be allocated. The memory is persistent, so eventually you will run out of memory with this.
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
static int* myVar = NULL;
if(myVar == NULL)
{
myVar = (int*)malloc(sizeof(int*), 10); // Using the system malloc
myVar[0] = 1;
}
myVar[0] *= 2;
}
In the case above, things are OK, except that the memory allocated by malloc
is never freed. When you do clear all
or clear mex
, the MEX-file will be cleared, the myVar
static variable will be deleted, but the memory allocated by malloc
is still there. You are leaking memory again. If you want to do it this way, you need to register a function to be run when the MEX-file exists, using mexAtExit()
.
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
static int myVar[10] = {1};
myVar[0] *= 2;
}
In the case above, we use a static variable to hold all our data, no dynamic memory allocation is used, we don't need to worry about leaking memory. I recommend this unless the array is very large.