mex文件中的分段错误

时间:2014-01-22 22:44:57

标签: c matlab segmentation-fault mex

以下是我在制表符分隔文件中编写的mex代码。 mex文件已创建,但它导致我的MATLAB突然结束并给出以下错误。任何人都可以在我出错的地方帮助我吗?如果需要任何进一步的信息,请告诉我

异常终止: 分段违规

#include "mex.h"
#include "matrix.h"
#include <stdio.h>
#include<string.h>
#include<stdlib.h>  

void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{   

    FILE *ptr_file;
    const char **field_names;       /* pointers to field names */
    char *buf[1024];
    char *temp[20];
    int count;
    int i, j, k, l;
    int date_field, mva_field, qc_load_field, air_field, qc_air_field, oil_field, qc_oil_field, wind_a_field, qc_wind_a_field, wind_b_field, qc_wind_b_field, wind_c_field, qc_wind_c_field, tamb1_field, qc_tamb1_field;
    char *NAME;
    NAME=mxArrayToString(prhs[0]);
    count = 0;
//open file to count elements   
    ptr_file =fopen(NAME,"r");
    if (ptr_file != NULL)
    {
//skip first 3 lines    
    fgets(buf, sizeof(buf), ptr_file);
    fgets(buf, sizeof(buf), ptr_file);
    fgets(buf, sizeof(buf), ptr_file);
//start counting no. of elements    
    while(fgets(buf, sizeof(buf), ptr_file) != NULL)
        count++;
    fclose(ptr_file);
    }
        field_names[0] = "date";
    field_names[1] = "mva";
    field_names[2] = "qc_load";
    field_names[3] = "air";
    field_names[4] = "qc_air";
    field_names[5] = "oil";
    field_names[6] = "qc_oil";
    field_names[7] = "wind_a";
    field_names[8] = "qc_wind_a";
    field_names[9] = "wind_b";
    field_names[10] = "qc_wind_b";
    field_names[11] = "wind_c";
    field_names[12] = "qc_wind_c"; 
    field_names[13] = "tamb1";
    field_names[14] = "qc_tamb1"; 

    plhs[0] = mxCreateStructMatrix(count, 1, 15, field_names);
    plhs[1] = mxCreateDoubleMatrix(1,1,mxREAL);
    date_field = mxGetFieldNumber(plhs[0],"date");
    mva_field = mxGetFieldNumber(plhs[0],"mva");
    qc_load_field = mxGetFieldNumber(plhs[0],"qc_load");
    air_field = mxGetFieldNumber(plhs[0],"air");
    qc_air_field = mxGetFieldNumber(plhs[0],"qc_air");
    oil_field = mxGetFieldNumber(plhs[0],"oil");
    qc_oil_field = mxGetFieldNumber(plhs[0],"qc_oil");
    wind_a_field = mxGetFieldNumber(plhs[0],"wind_a");
    qc_wind_a_field = mxGetFieldNumber(plhs[0],"qc_wind_a");
    wind_b_field = mxGetFieldNumber(plhs[0],"wind_b");
    qc_wind_b_field = mxGetFieldNumber(plhs[0],"qc_wind_b");
    wind_c_field = mxGetFieldNumber(plhs[0],"wind_c");
    qc_wind_c_field = mxGetFieldNumber(plhs[0],"qc_wind_c");
    tamb1_field = mxGetFieldNumber(plhs[0],"tamb1");
    qc_tamb1_field = mxGetFieldNumber(plhs[0],"qc_tamb1");


//open file again for storing elements columnwise
    ptr_file =fopen(NAME,"r");
    if (ptr_file != NULL)
    {
//skip first 3 lines    
    fgets(buf, sizeof(buf), ptr_file);
    fgets(buf, sizeof(buf), ptr_file);
    fgets(buf, sizeof(buf), ptr_file);  
//start collecting data 
    for(i=0;i<count;i++){   //increment line
        //get line
        fgets(buf, sizeof(buf), ptr_file);
        j=0;
        k=0;
        //extract first word
        while(buf[j] != '\t'){
            temp[k] = buf[j];
            j++;
            k++;
        }
        temp[k] = '\0';
        j++;
        mxSetFieldByNumber(plhs[0],i,date_field,mxCreateString(temp));
//      strcpy(elem[i].date, temp);

        //extract second word
        k=0;
        while(buf[j] != '\t'){
            temp[k] = buf[j];
            j++;
            k++;
        }
        temp[k] = '\0';
        j++;
//      elem[i].mva = atof(temp);
        *mxGetPr(plhs[1]) = atof(temp);
        mxSetFieldByNumber(plhs[0],i,mva_field,plhs[1]);    

        //extract third word
        k=0;
        while(buf[j] != '\t'){
            temp[k] = buf[j];
            j++;
            k++;
        }
        temp[k] = '\0';
        j++;
//      strcpy(elem[i].qc_load, temp);  
        mxSetFieldByNumber(plhs[0],i,qc_load_field,mxCreateString(temp));
// similarly for other fields of the structure. 
    fclose(ptr_file);
    }
}

1 个答案:

答案 0 :(得分:0)

你得到了一个段错误,因为而不是field_names指向你可以视为const char *数组的某个地方,它无处可指,因为它没有被初始化。因此

const char **field_names;    /* pointer to nowhere */
...
field_names[0] = "date";     /* dereferences invalid pointer and BANG */

你想要的实际上是:

const char *field_names[15]; /* array of pointers to const char */
...
field_names[0] = "date";     /* all is well and good */
...

键C事实:指针不是数组,数组不是指针,但在某些情况下,数组将被隐式转换为指向其第一个元素的指针 - 例如将field_names数组传递给mxCreateStructMatrix()代替const char **仍然是正确的。


然而,解决这个问题然后你会遇到这个问题:

plhs[1] = mxCreateDoubleMatrix(1,1,mxREAL);

首先,由于您尚未检查nlhs是否至少为2,plhs[1]可能不存在,并且当您尝试设置其值时同样会爆炸。 IIRC,设置plhs[0]而不检查可能确定,因为即使nlhs == 0plhs[0] 应该指向Ans而不是显式的输出变量,但实际上最好在做任何事情之前检查nlhs并采取相应的行动。同样地,在不检查prhs[0]的情况下使用nrhs > 0是不可取的。

其次,稍后您将最终将同一mxArray分配给多个结构的多个字段,这些字段不是一个有效的事情(并且可能导致Matlab稍后因堆损坏而崩溃)。即使它被允许,我也不认为你希望整个结构数组中的每个数字字段都指向一个被覆盖了一千次的单double ......

第三,我完全不理解plhs[1]的使用,除非你真的想要一个强制性的第二个输出“无论读取的最后一个数字是什么”。我怀疑你要的是这个:

mxArray *mxtmp;
...
    /* in parsing loop */
    mxtmp = mxCreateDoubleScalar(atof(temp));
    mxSetFieldByNumber(plhs[0], i, mva_field, mxtmp); 

在其他地方,虽然你可以在指针中存储char值,但这不是一个理智或有意义的事情,在这种情况下显然是另一个错误:

char *buf[1024];  /* array of pointers to char - wrong */
char *temp[20];

char buf[1024];   /* array of char - right */
char temp[20];