MATLAB: Segmentation error in mex file

cMATLABmexsegmentation fault

Here is the mex code I wrote to read in a tab-delimited file. The mex file got created but it causes my MATLAB to end abruptly and give the following error. Can anyone help me where I am going wrong? Please let me know if any further information is required. I have attached the error report though I do not know if it can help
Abnormal termination: Segmentation violation
#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);
}
}

Best Answer

I don't see anywhere where you allocate field_names:
const char **field_names; /* pointers to field names */
:
field_names[0] = "date";
That, in and of itself, will bomb your code and MATLAB.
This line will bomb your code if the caller does not request 2 outputs:
plhs[1] = mxCreateDoubleMatrix(1,1,mxREAL);
This line will eventually bomb MATLAB because you can't re-use mxArray pointers (plhs[1]) this way when stuffing them into a cell array or struct array:
mxSetFieldByNumber(plhs[0],i,mva_field,plhs[1]);
You need to create a brand new mxArray for each of these iterative calls, and not re-use plhs[1] over and over. In fact, you should not use plhs[1] here at all ... use a different mxArray pointer. (There is another unofficial way involving bumping up the reference count, but I will not go into that here)
Related Question