I have a mex function that takes a double precision input vector, downcasts the precision to a temporary single precision vector, does some processing and then upcasts the result of the processing to double precision again.
The following simplified code example compiles and illustrates this process.
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int xM = mxGetM(prhs[0]);
int xN = mxGetN(prhs[0]);
int totalNumElements = xM*xN;
plhs[0] = mxCreateDoubleMatrix(xM,xN,mxREAL);
double* out = mxGetPr(plhs[0]);
double* in = mxGetPr(prhs[0]);
float out32[totalNumElements];
float in32[totalNumElements];
// ---------> DOWNCAST <---------
for (int mm = 0; mm < totalNumElements; ++mm)
in32[mm] = (float)in[mm];
// ---------- DOWNCAST ----------
// Do some single precision signal processing (just copy for this example)
for (int mm = 0; mm < totalNumElements; ++mm)
out32[mm] = in32[mm];
// ---------> UPCAST <---------
for (int mm = 0; mm < totalNumElements; ++mm)
out[mm] = (double)out32[mm];
// ---------- UPCAST ----------
}
On my machine, calling the compiled mex function like this works fine . .
>> x = randn(1e6,1); y=demo(x);
...but calling it like this causes Matlab to close unexpectedly
>> x = randn(1e7,1); y=demo(x);
Seeing as the crash is caused by an increase in the size of the input vector, I'm guessing that the error is due to a failed memory allocation. How can I gracefully quit to Matlab giving an error message if such an error occurs? Thanks.
OK, one way to do this would be to replace the stack allocated variables with the C-style . . .
float* in32 = (float*)mxCalloc(totalNumElements, sizeof(float));
float* out32 = (float*)mxCalloc(totalNumElements, sizeof(float));
When there is a memory error, Matlab neatly gives the following error . . .
Error using demo Out of memory.
Type HELP MEMORY for your options.
No need for try-catch
blocks or exceptions.
Another method is to use C++ style std::exception
. The stack allocated variables can be replaced with the following ...
float* in32;
float* out32;
try
{
in32 = new float[totalNumElements];
out32 = new float[totalNumElements];
}
catch (std::exception& e)
{
std::string msg = std::string("Aw snap: ") + e.what();
mexErrMsgTxt(msg.c_str());
}
When there is a memory error, Matlab neatly gives the following error . . .
Error using demo
Aw snap: std::bad_alloc
Method 1 is more compact and better integrated with the mex API. It is probably best to use method 1 in the mex gateway function and method 2 in a library that may have uses beyond just making a Matlab extension. Both these methods require you to use mxFree
(mxCalloc
solution) or delete
(new
solution) in order to fee the memory allocated on the heap for in32
and out32
. I still don't know how to detect or deal with stack overflows