Skip to content
Advertisement

Reading corrupt file, segmentation fault

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. */
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement