访问冲突终止调用slasd4 mex

时间:2016-11-15 13:22:27

标签: matlab mex lapack

我正在尝试构建一个MEX文件来调用MATLAB中的Lapack命令slasd4。构建mex文件成功,但是当我尝试使用该命令时,它会崩溃MATLAB并以消息结束

  

异常终止:访问冲突。

有人可以帮我解决这个问题吗?我正在使用带有内置插件的MATLAB R2016b来使用MEX文件。

这是我的mex文件:

#include "mex.h"
#include "lapack.h"

void mexFunction(int nlhs,       mxArray *plhs[], 
                 int nrhs, const mxArray *prhs[])
{
    mwSize n, i, info = 0;
    float  *z, *d, *delta, *work, *sigma, rho;

    /* verify input/output arguments */
    if (nrhs > 4) {
        mexErrMsgTxt("Too many input arguments.");
    }
    if (nlhs > 3) {
        mexErrMsgTxt("Too many output arguments.");
    }

    /* dimensions of input matrix */
    n = mxGetN(prhs[0]); 

    /* create output matrices */
    plhs[0] = mxCreateNumericMatrix(n, 1, mxSINGLE_CLASS, mxREAL);
    plhs[1] = mxCreateNumericMatrix(n, 1, mxSINGLE_CLASS, mxREAL);
    plhs[2] = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);

    /* get pointers to data */
    i     = (mwSignedIndex) prhs[3];

    d     = (float *) mxGetPr(prhs[0]);
    z     = (float *) mxGetPr(prhs[1]);
    rho   = (float)   mxGetScalar(prhs[2]);        

    delta = (float *) mxGetPr(plhs[0]);
    work  = (float *) mxGetPr(plhs[1]);
    sigma = (float *) mxGetPr(plhs[2]);

    /* Call Lapack function */
    slasd4(&n, &i, d, z, delta, &rho, sigma, work, &info);

    /* check if call was successful */
    if (info < 0) {
        mexErrMsgTxt("Illegal values in arguments.");
    } else if (info > 0) {
        mexErrMsgTxt("Failed to converge.");
    }
}

这是一个简单的测试示例:

D = [2; 0];
z = [1;0];
[delta, work, sigma] = slasd4(D,z,-1,1);

这是故障的起始堆栈跟踪:

[  0] 0x000000000b8c15b0      C:\Users\Joni\Desktop\NLA\Paper\slasd4.mexw64+00005552 mexfilerequiredapiversion+00000032
[  1] 0x000000000b8c1561      C:\Users\Joni\Desktop\NLA\Paper\slasd4.mexw64+00005473 mexFunction+00000305
[  2] 0x00000000fc5fc5d1 C:\Program Files\MATLAB\R2016b\bin\win64\libmex.dll+00116177 mexRunMexFile+00000129
[  3] 0x00000000fc5fb2e2 C:\Program Files\MATLAB\R2016b\bin\win64\libmex.dll+00111330 mexFeature_mexver+00001794
[  4] 0x00000000fc5fa506 C:\Program Files\MATLAB\R2016b\bin\win64\libmex.dll+00107782 mexUnlock+00020182

1 个答案:

答案 0 :(得分:0)

与数据类型等相关的几个问题。使用MATLAB提供的库的BLAS和LAPACK调用所使用的所有整数变量通常应该键入mwSignedIndex,而不是mwSize。此外,如果传入的变量的基础数据类型是双精度数,那么只需将(浮点数)指向它们,就不能神奇地将数据更改为浮点数。因此,您需要确保输入数据是正确的类。在前面,您应该对批次进行更多检查,以获取变量类和大小等。以下是一些带有额外前期检查的代码,以及一些代码更正:

#include "mex.h"
#include "lapack.h"

void mexFunction(int nlhs,       mxArray *plhs[], 
                 int nrhs, const mxArray *prhs[])
{
mwSignedIndex n, i, info = 0;  /* CHANGED */
float  *z, *d, *delta, *work, *sigma, rho;
mxArray *plhs0, *plhs1, *plhs2;  /* NEW */

/* verify input/output arguments */
if (nrhs != 4) {  /* CHANGED */
    mexErrMsgTxt("Need exactly 4 inputs.");  /* CHANGED */
}
if (nlhs > 3) {
    mexErrMsgTxt("Too many output arguments.");
}
/* NEW */
if( !mxIsSingle(prhs[0]) || mxIsComplex(prhs[0]) ) {
    mexErrMsgTxt("1st argument must be a real single class variable");
}
if( !mxIsSingle(prhs[1]) || mxIsComplex(prhs[1]) ) {
    mexErrMsgTxt("2nd argument must be a real single class variable");
}
if( !mxIsNumeric(prhs[2]) || mxIsComplex(prhs[2]) || mxGetNumberOfElements(prhs[2]) != 1 ) {
    mexErrMsgTxt("3rd argument must be a real numeric scalar variable");
}
if( !mxIsNumeric(prhs[3]) || mxIsComplex(prhs[3]) || mxGetNumberOfElements(prhs[3]) != 1 ) {
    mexErrMsgTxt("4th argument must be a real numeric scalar variable");
}

/* dimensions of input matrix */
n = mxGetN(prhs[0]); 

/* create output matrices */
plhs0 = mxCreateNumericMatrix(n, 1, mxSINGLE_CLASS, mxREAL);  /* CHANGED */
plhs1 = mxCreateNumericMatrix(n, 1, mxSINGLE_CLASS, mxREAL);  /* CHANGED */
plhs2 = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);  /* CHANGED */

/* get pointers to data */
i     = (mwSignedIndex) mxGetScalar(prhs[3]);  /* CHANGED */
d     = (float *) mxGetData(prhs[0]);  /* CHANGED */
z     = (float *) mxGetData(prhs[1]);  /* CHANGED */
rho   = (float)   mxGetScalar(prhs[2]);        

delta = (float *) mxGetData(plhs0);  /* CHANGED */
work  = (float *) mxGetData(plhs1);  /* CHANGED */
sigma = (float *) mxGetData(plhs2);  /* CHANGED */

/* Call Lapack function */
slasd4(&n, &i, d, z, delta, &rho, sigma, work, &info);

/* check if call was successful */
if (info < 0) {
    mexErrMsgTxt("Illegal values in arguments.");
} else if (info > 0) {
    mexErrMsgTxt("Failed to converge.");
}
plhs[0] = plhs0;  /* NEW */
if( nlhs > 1 ) plhs[1] = plhs1;  /* NEW */
if( nlhs > 2 ) plhs[2] = plhs2;  /* NEW */
}

这是跑步的结果:

>> D = [2; 0];
>> z = [1;0];
>> [delta, work, sigma] = slasd4(D,z,-1,1)
??? Error using ==> slasd4
1st argument must be a real single class variable

>> [delta, work, sigma] = slasd4(single(D),z,-1,1)
??? Error using ==> slasd4
2nd argument must be a real single class variable

>> [delta, work, sigma] = slasd4(single(D),single(z),-1,1)
delta =
     1
work =
     1
sigma =
    1.7321

我只做了足够的改动让你超越了seg的错误。我没有检查实际函数调用本身的任何内容,以确保您具有工作变量的正确尺寸,或者变量具有适当的数据等。