Search code examples
c++matlabexceptionmemory-managementmex

Gracefully quit from mex file if there is a memory allocation error


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.


Solution

  • Method 1

    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.

    Method 2

    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

    Notes

    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