c - mex 文件中的段错误

标签 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);
    }
}

最佳答案

您遇到了段错误,因为 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] 很可能不存在,并且当您尝试设置其值时同样会崩溃值(value)。 IIRC,设置plhs[0]而不检查可能可以,因为即使nlhs == 0plhs[0] 应该指向 Ans 而不是显式输出变量,但实际上,在执行任何操作之前检查 nlhs 并采取相应行动是一个很好的做法。同样,不建议使用 prhs[0] 而不检查 nrhs > 0

其次,稍后您将最终将同一个 mxArray 分配给多个结构的多个字段,这不是有效的操作(并且可能会导致 Matlab 由于堆损坏而崩溃) 。即使允许,我也不认为您希望整个结构数组中的每个数字字段都指向一个已被覆盖 n 千次的 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];

关于c - mex 文件中的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21295644/

相关文章:

c - 算法-使用外部编解码器/调制解调器处理抖动和漂移

c - 从文件填充动态数组

c# - 从 C# 运行 64 位编译的 MATLAB 函数

c - 在不知道索引的情况下在 C 中迭代多维数组

java - 为什么编译的 Java 类文件比 C 编译的文件小?

c++ - 如何便携地找出 min(INT_MAX, and(INT_MIN))?

matlab - 使用 'datenum' 创建间隔

matlab - 从 MATLAB 图形对象继承

c - 二叉树Find_parent方法导致SegFault

c++ - 回溯结果没有揭示崩溃位置