I run my program by passing it a bunch of directories like this:
./myprogram *
Each directory is a separate set of files that I am parsing for data which I then create into a spreadsheet. Each directory is a different row of the spreadsheet. I want to only put reliable data in the spreadsheet and so if an entry is missing I leave it out. It seems to work well on most of the directories but on some directories I get a segmentation fault during one of my parse functions.
I have noticed that every file that results in a segmentation fault is unopenable with gedit. It gives this error:
gedit has not been able to detect the character coding. Please check that you are not trying to open a binary file. Select a character coding from the menu and try again.
However, I am able to display the file by use the cat or tail commands.
The specific function that results in the segmentation fault is the fscanf function below, that I use to read a single line at a time. (increasing the size of the buffers did not help)
char *line = malloc(1000*sizeof(char)); char *garbage = malloc(1000*sizeof(char)); while(!feof(infile) ) { fscanf(infile,"%[^n]%[n]",line,garbage); //parse the line }
Does anyone know why the file may be unopenable with gedit? Is it corrupted? Is there a way I can return an error code in my parse function instead of seg faulting?
Advertisement
Answer
You have a buffer overrun in fscanf()
. This is probably causing the program to write past the end of the array, overwrite a pointer somewhere, and crash.
Your options are:
Read a line into an input buffer with fgets()
and parse it with sscanf()
if necessary, probably what you want, or
Tell fscanf()
the sizes of the buffers, e.g. fscanf( infile, " %999[^n]%*[n]", line );
Additionally, you almost never want while (!feof(infile))
. This will stop when it reads past end-of-file.
So you should really change this to:
static const size_t LINE_LEN = 1000; while (fgets( line, LINE_LEN, infile )) /* Do stuff with line. */
Or
while ( 1 == fscanf( infile, " %999[^n]%*[n]", line ) ) /* Do stuff with line. */