从 MATLAB 调用 .c 文件会产生分段违规

Calling a .c file from MATLAB yields a segmentation violation

我想 运行 来自 matlab 的两个 C 程序 "hello1.c" 和 "hello2.c"。

我的hello1.c代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <mex.h>
#include <math.h>
#include "matrix.h"


void funcc(double **f, double **x, long n, long b, double lambda, double theta)
{
    long i;
    long j;
    double u,v,y,z,w;
    y = theta*lambda;
    w = lambda*lambda;
    z = 0.5*(theta+1.0)*w;

    u = 0.0;
    for(i=0;i<n;i++)
    {
        for(j=0;j<b;j++)
        v = fabs(x[i][j]);
        if (v <= lambda)
            u += lambda*v;
        else if (v > y)
            u += z;
        else
            u += 0.5*(v*(2*y - v) - w)/(theta-1.0);
        }
    **f = u;
    return;
}


void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
    /*set up input arguments */
    double **x       =            mxGetPr(prhs[0]);
    long     n      =      (long)mxGetScalar(prhs[1]);
    long     b      =      (long)mxGetScalar(prhs[2]);
    double  lambda  =            mxGetScalar(prhs[3]);
    double  theta   =            mxGetScalar(prhs[4]);
    int     type    =       (int)mxGetScalar(prhs[5]);

    double **f;


    /* set up output arguments */
    plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);

    f=mxGetPr(plhs[0]);

    funcc(f, x, n, b, lambda, theta);
    }

我的hello2.c代码如下:

long mymin(double *x, long n)
{
    long i, ind;
    double temp;
    temp = x[0];
    ind = 0;
    for (i=1;i<n;i++)
    {
        if (x[i] < temp)
        {
            ind = i;
            temp = x[i];
        }

    }
    return ind;
}


        void funnn(double *x, double *d, long n, long b, double lambda, double theta)
        {
            long i;
            long j;
            double u,z,w;
            double xtemp[3],ytemp[3];
            z = theta*lambda;
            w = lambda*lambda;
            for(i=0;i<n;i++)
            {
                for(j=0;j<b;j++)
                u = fabs(d[j*n + i]);
                xtemp[0] = min(lambda,max(0,u - lambda));
                xtemp[1] = min(z,max(lambda,(u*(theta-1.0)-z)/(theta-2.0)));
                xtemp[2] = max(z,u);

                ytemp[0] = 0.5*(xtemp[0] - u)*(xtemp[0] - u) + lambda*xtemp[0];
                ytemp[1] = 0.5*(xtemp[1] - u)*(xtemp[1] - u) + 0.5*(xtemp[1]*(-xtemp[1] + 2*z) - w)/(theta-1.0);
                ytemp[2] = 0.5*(xtemp[2] - u)*(xtemp[2] - u) + 0.5*(theta+1.0)*w;
                x[j*n + i] = xtemp[mymin(ytemp,3)];
                x[j*n + i] = d[j*n + i]>= 0 ? x[j*n + i] : -x[j*n + i];
            }
            //return;
        }



        void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
        {
            /*set up input arguments */
            double* d       =            mxGetPr(prhs[0]);
            long     n      =      (long)mxGetScalar(prhs[1]);
            long     b      =      (long)mxGetScalar(prhs[2]);
            double  lambda  =            mxGetScalar(prhs[3]);
            double  theta   =            mxGetScalar(prhs[4]);

            double *x;


            /* set up output arguments */
            plhs[0] = mxCreateDoubleMatrix(n,b,mxREAL);

            x=mxGetPr(plhs[0]);

            funnn(x, d, n, b, lambda, theta);
        }

问题是,当我编译调用我的 C 函数的 MATLAB 代码时(当然我已经编写了 mex hello1.cmex hello2.c),MATLAB returns 我显示 MATLAB 遇到内部问题并需要关闭的屏幕。事实上,这个错误是在 MEX 文件 运行ning.

时检测到的

难道是我的函数mexFunction没写对?任何知道如何编写 MEX 函数的人都可以帮助我吗?

非常感谢任何帮助!

对于 hello1.c,MEX 中的 mxGetPr 不会 给你一个双指针。它为您提供了一个 指针,对于 2D 内存,它采用列优先布局。您必须通过以下语法访问二维数组中的正确值,假设 ij 是您要访问的二维数组中的行和列:

ind = j*rows + i;

... 因此,如果您想要在二维数组 x 中定位 (i,j),只需执行以下操作:

double val = x[j*rows + i];

rows 是二维数组中的总行数。因此,您必须在代码中更正此问题才能正确访问二维数组。您还必须对 f 执行相同的操作。此外,您在第二个 for 循环周围遗漏了一对大括号,稍后我将解释原因。

因此,您的函数变为:

void funcc(double *f, double *x, long n, long b, double lambda, double theta) // Note change in function declaration
{
    long i;
    long j;
    double u,v,y,z,w;
    y = theta*lambda;
    w = lambda*lambda;
    z = 0.5*(theta+1.0)*w;

    u = 0.0;
    // n is the rows, b is the columns
    for(i=0;i<n;i++)
    {
        for(j=0;j<b;j++) { // Added
        v = fabs(x[j*n + i]); // Change here
        if (v <= lambda)
            u += lambda*v;
        else if (v > y)
            u += z;
        else
            u += 0.5*(v*(2*y - v) - w)/(theta-1.0);
        } // Added
    } 
    *f = u; // Change
    //return; // Superfluous
}

您的 mexFunction 现在变成:

void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
    /*set up input arguments */
    double *x       =            mxGetPr(prhs[0]); // Change
    long     n      =      (long)mxGetScalar(prhs[1]);
    long     b      =      (long)mxGetScalar(prhs[2]);
    double  lambda  =            mxGetScalar(prhs[3]);
    double  theta   =            mxGetScalar(prhs[4]);
    int     type    =       (int)mxGetScalar(prhs[5]);

    double *f; // Change

    /* set up output arguments */
    plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);

    f=mxGetPr(plhs[0]);

    funcc(f, x, n, b, lambda, theta);
}

对于hello2.c,除了第二个for循环外,一切都很好。您只需要用花括号将代码块括起来:

           for(i=0;i<n;i++)
           {
                for(j=0;j<b;j++) { // added
                u = fabs(d[j*n + i]);
                xtemp[0] = min(lambda,max(0,u - lambda));
                xtemp[1] = min(z,max(lambda,(u*(theta-1.0)-z)/(theta-2.0)));
                xtemp[2] = max(z,u);

                ytemp[0] = 0.5*(xtemp[0] - u)*(xtemp[0] - u) + lambda*xtemp[0];
                ytemp[1] = 0.5*(xtemp[1] - u)*(xtemp[1] - u) + 0.5*(xtemp[1]*(-xtemp[1] + 2*z) - w)/(theta-1.0);
                ytemp[2] = 0.5*(xtemp[2] - u)*(xtemp[2] - u) + 0.5*(theta+1.0)*w;
                x[j*n + i] = xtemp[mymin(ytemp,3)];
                x[j*n + i] = d[j*n + i]>= 0 ? x[j*n + i] : -x[j*n + i];
                } //added
            } 

两个文件都需要额外的大括号的原因是,如果省略它们,C 只会将循环后的第一行视为循环体。 for 循环完成后的其余代码将被执行,而不是循环的一部分,这就是您遇到分段错误的原因。