这是我编写的用于在制表符分隔文件中读取的 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 == 0
,plhs[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/