I would highly advise combining your multiple mex routines into one mex routine that you call with a directive (e.g., a string) indicating the action you want the mex routine to take (e.g., 'init', 'process', 'clear', etc.). That way all of the memory allocation and usage is within one mex routine and can be more easily managed to avoid memory access issues and memory leaks. That being said, here are some problems I observe with your code:
Invalid memory:
myStruct **c_ptr;
plhs[0] = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL); <-- create the output variable
c_ptr = (myStruct **) mxGetData(plhs[0]); <-- get a pointer to the plhs[0] data area
:
myStruct *c = (myStruct *) mxMalloc(sizeof(myStruct)); <-- memory is on garbage collection list
:
*c_ptr = c; <-- pointer to memory placed into plhs[0], but pointer still on garbage collection list
As soon as your mex function returns to the caller, the memory behind the c pointer is free'd by the automatic garbage collection and is invalid. Any further access of this memory downstream, which you do, will either give garbage results or crash MATLAB. You could solve this by the following:
mexMakeMemoryPersistent(c); <-- ensure c memory is not on garbage collection list
But then you risk a memory leak because you currently have no code to free c and you are not remembering the c pointer inside your mex function. So you would need to add a mexAtExit function to do this. You might also want to have a directive (e.g., 'clear') that does this via user command.
What you really need to do is remember the c pointer inside your mex function (e.g., as a top level global variable) so that you can free it when necessary (mex routine is cleared or user uses the 'clear' command). Top level global variables retain their values between mex calls as long as you don't clear the mex function from memory.
This becomes very tricky if you have the pointer value inside a MATLAB variable in the workspace. If you pass that pointer value into the mex routine, the mex routine would need to be able to check its validity before using it (e.g., compare it to the top level global variable value) or again you risk a crash, etc.
Also, you are using an mxINT32_CLASS variable to hold a pointer value ... this will not work if you are running a 64-bit version of MATLAB where pointers are 64-bits.
Another option would be to pass the structure itself back in the plhs[0] variable and let MATLAB handle this memory just like any other normal variable. This avoids remembering the pointer and memory deallocation issues entirely. This would only make sense if the struct contained only data and not pointers to resources. E.g., a rough outline:
myStruct *c = (myStruct *) mxMalloc(sizeof(myStruct));
:
plhs[0] = mxCreateNumericMatrix(0, 0, mxUINT8_CLASS, mxREAL);
mxSetData(plhs[0],c); <-- c no longer on garbage collection list
mxSetM(plhs[0],1);
mxSetN(plhs[0],sizeof(myStruct));
Best Answer