从MATLAB调用.c文件会导致分段违规

时间:2016-07-20 15:23:33

标签: c matlab mex

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

我的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);
        }

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

这是因为我的函数mexFunction编写不正确吗?任何知道如何编写MEX功能的人都可以帮助我吗?

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

对于hello1.c,MEX中的mxGetPr 会为您提供双指针。它为您提供单个指针,对于2D内存,它采用列主要布局。您必须通过以下语法访问2D数组中的正确值,前提是ij是您要访问的2D数组中的行和列:

ind = j*rows + i;

...因此,如果您想在2D数组(i,j)中找到位置x,只需执行以下操作:

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

rows是2D数组中的总行数。因此,您必须在代码中更正此问题才能正确访问2D阵列。您还必须对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循环结束后的其余代码将被执行,而不是循环的一部分,这就是您获得分段错误的原因。