'new' in MEX file causes crash

1 view (last 30 days)
John Matthews
John Matthews on 15 Dec 2015
Commented: James Tursa on 16 Dec 2015
Hi - I've got some code that causes my MEX file to crash (Matlab R2015b):
#define USE_CONST_SIZE 0
#if USE_CONST_SIZE
const size_t rows = 8, cols = 8;
#else
size_t rows, cols, rowsTmp, colsTmp;
getMatrixSize(prhs[0], rows, cols, "rhs0");
getMatrixSize(prhs[1], rowsTmp, colsTmp, "rhs1");
if ((rows != rowsTmp) || (cols != colsTmp) || (rows != 8) || (cols != 8))
throw std::runtime_error("mismatched arguments");
#endif
#define USE_NEW 1
#if USE_NEW
auto* const lhs = new std::complex<float>[rows * cols];
auto* const rhs = new std::complex<float>[rows * cols];
auto* const result = new std::complex<float>[rows * cols];
#else
alignas(64) std::complex<float> lhs[rows * cols];
alignas(64) std::complex<float> rhs[rows * cols];
alignas(64) std::complex<float> result[rows * cols];
#endif
So with USE_NEW=1 and USE_CONST_SIZE=0, the rows and cols values are obtained from the size of an 8x8 Matlab matrix holding the test data, and the size of the new isn't known at compile time. This results in a crash in the first new (I've used debug to confirm that this is where the crash occurs).
But with USE_CONST_SIZE=1, so the size of the new is known at compile time, there's no crash. Also, if USE_NEW=0 resulting in local rather than dynamically allocated arrays, there's no crash. (Code only compiles when USE_CONST_SIZE=1.)
I'm relatively new to Matlab/MEX, and googling suggests I should be using mxMalloc() rather than new, so I guess the question is somewhat academic. But I haven't seen anything that explains this behaviour.
So out of curiosity, any ideas?
Cheers John
Hi James - I can post the code, although note that I raise an exception if rows or cols is not 8, which should guarantee their values.
Here you go:
std::vector<size_t>
dimensions(const mxArray* data)
{
auto mxDimensions = mxGetDimensions(data);
auto numDimensions = mxGetNumberOfDimensions(data);
return std::vector<size_t>(mxDimensions, mxDimensions + numDimensions);
}
void
getMatrixSize (const mxArray* data, size_t& num_rows, size_t& num_cols,
const std::string& description)
{
const auto& dims = dimensions(data);
if (dims.size() != 2)
throw std::runtime_error ("Expected argument \"" + description + "\" to be 2-d matrix argument");
num_rows = dims[0];
num_cols = dims[1];
}
Cheers John
  1 Comment
James Tursa
James Tursa on 15 Dec 2015
I would suggest you replace your throw code with MATLAB API code, and print out some values to the screen. E.g.,
getMatrixSize(prhs[0], rows, cols, "rhs0");
getMatrixSize(prhs[1], rowsTmp, colsTmp, "rhs1");
if ((rows != rowsTmp) || (cols != colsTmp) || (rows != 8) || (cols != 8)) {
mexPrintf("rows = %d , rowsTmp = %d\n",rows,rowsTmp);
mexPrintf("cols = %d , colsTmp = %d\n",cols,colsTmp);
mexErrMsgTxt("mismatched arguments");
}
and
if (dims.size() != 2) {
mexPrintf("dims.size() = %d\n",dims.size());
mexErrMsgTxt("Expected argument to be 2-d matrix argument");
}
And if you get past that, then we can worry about the new.

Sign in to comment.

Answers (1)

James Tursa
James Tursa on 15 Dec 2015
Edited: James Tursa on 15 Dec 2015
You don't show enough code. E.g., these lines:
getMatrixSize(prhs[0], rows, cols, "rhs0");
getMatrixSize(prhs[1], rowsTmp, colsTmp, "rhs1");
What is the prototype for getMatrixSize? If rows and cols are passed by value, which is the default passing mechanism in C/C++, then rows and cols will not be changed in the calling routine, resulting in rows and cols having undefined values in downstream code. Same comment for rowsTmp and colsTmp. Can you post the code for getMatrixSize?
Also, do you have anything that is catching your throw std::runtime_error("mismatched arguments")? Normally I would have expected to use MATLAB API functions for this (e.g., mexErrMsgTxt) instead of using the C++ throw.
Regarding mxMalloc etc vs new, the advantage of using MATLAB API functions for memory allocation is that the memory is automatically garbage collected for you. Also, out-of-memory errors are automatically handled and result in the routine exiting with an error back to the caller.
  2 Comments
John Matthews
John Matthews on 16 Dec 2015
Thanks again James. I've amended my code to:
#if USE_NEW
mexPrintf("rows=%u cols=%u\n", rows, cols);
mexPrintf("lhs\n");
auto* const lhs = new std::complex<float>[rows * cols];
mexPrintf("rhs\n");
auto* const rhs = new std::complex<float>[rows * cols];
mexPrintf("result\n");
auto* const result = new std::complex<float>[rows * cols];
which results in:
rows=8 cols=8
lhs
before I get the 'MATLAB has encountered an internal problem and needs to close' window.
As I mentioned previously, this is no longer a problem as I've changed my 'real' code to use mxMalloc(). Just curious, and presumably Mathworks might want to know if there's a bug (unlikely, I know).
James Tursa
James Tursa on 16 Dec 2015
Out of curiosity, what happens if you replace the "auto" keyword with the actual type?

Sign in to comment.

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!