我有一个mex函数,它采用双精度输入向量,将精度向下转换为临时单精度向量,进行一些处理,然后再将处理结果向上转换为双倍精度。
以下简化代码示例编译并说明了此过程。
#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 ----------
}
在我的机器上,调用这样编译的mex函数可以正常工作。 。
>> x = randn(1e6,1); y=demo(x);
...但是这样调用会导致Matlab意外关闭
>> x = randn(1e7,1); y=demo(x);
看到崩溃是由输入向量的大小增加引起的,我猜这个错误是由于内存分配失败引起的。如果出现这样的错误,我如何优雅地退出Matlab给出错误消息?感谢。
答案 0 :(得分:2)
好的,一种方法是用C风格替换堆栈分配的变量。 。
float* in32 = (float*)mxCalloc(totalNumElements, sizeof(float));
float* out32 = (float*)mxCalloc(totalNumElements, sizeof(float));
当出现内存错误时,Matlab会巧妙地给出以下错误。 。
使用demo内存不足时出错。
键入HELP MEMORY以获取选项。
无需try-catch
个阻止或例外。
另一种方法是使用C ++样式std::exception
。堆栈分配的变量可以替换为以下...
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());
}
当出现内存错误时,Matlab会巧妙地给出以下错误。 。
使用演示
时出错Aw snap:std :: bad_alloc
方法1更紧凑,更好地与mex API集成。最好在库中的mex网关函数和方法2中使用方法1,这可能只是在进行Matlab扩展时使用。这两种方法都要求您使用mxFree
(mxCalloc
解决方案)或delete
(new
解决方案),以便为in32
的堆上分配的内存付费和out32
。我仍然不知道如何检测或处理堆栈溢出