【问题标题】:Access violation termination calling slasd4 mex访问冲突终止调用 slasd4 mex
【发布时间】:2016-12-22 10:18:05
【问题描述】:

我正在尝试构建一个 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

【问题讨论】:

  • 我不知道 slasd4 在 C 中的正常签名,但事实上你只传递指针已经让我觉得很奇怪......
  • 另外,n 未签名 (mwSize),i 已签名 (mwSignedIndex),这很奇怪。此外,您不能将指向 mxArrays 的指针转换为 mwSignedIndex 以获取它们的大小...您不是要调用 mxGetN() 吗?
  • 您能否提供指向在这种情况下使用的slasd4 上的某种文档的链接?
  • 另外,如果您在 MATLAB 中调用 slasd4(1),您将遇到访问冲突,因为您尚未检查 nrhs &lt; 4 时会发生什么,但仍直接索引 prhs[3]
  • 这是用 Fortran 编写的,但你是用 C 编写的。C 包装器的签名是什么样的?

标签: matlab mex lapack


【解决方案1】:

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

#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 错误。我没有检查有关实际函数调用本身的任何内容,以确保您具有正确的工作变量尺寸,或者变量具有适当的数据等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多