Segmentation error in mex file
4 views (last 30 days)
Show older comments
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);
}
}
0 Comments
Accepted Answer
James Tursa
on 23 Jan 2014
Edited: James Tursa
on 23 Jan 2014
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)
3 Comments
James Tursa
on 23 Jan 2014
Edited: James Tursa
on 23 Jan 2014
You only need one mxArray * variable, you just need to create the mxArray that it points to new each iteration. E.g.,
mxArray *mx;
:
LOOP {
mx = mxCreateWhatever(etc);
mxSetFieldByNumber(etc,etc,etc,mx);
}
Note that I have only one pointer variable, mx, but at each iteration it points to a brand new created mxArray.
As for the error you were getting, I could only comment if I saw the code itself (but it sounds like you had a pointer indirection issue).
Finally, no need to apologize. We have all been there and some of this stuff is not well documented (or even documented at all).
More Answers (1)
Bruno Pop-Stefanov
on 22 Jan 2014
My intuition tells me that you get this error when you try to access temp[20]. You allocate an array temp of only 20 char, but you never check that k is less than 20. It's enough to have 20 characters (or more) between two tabs to crash your program.
Allocate a bigger array for temp and add if statements to check that you never go out of bounds when writing into temp and buf.
See Also
Categories
Find more on Whos in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!