Tony Tony - 1 month ago 23
C Question

fscanf Segmentation Fault: 11

I am trying to get data from a .tsv4 file. Whenever the code is run it returns with a segmentation fault: 11. The goal of the code is to store the unknown numbers into an array without knowing the amount of numbers in the file. The file I'm trying to access has 92 float values, and it stores them properly. But it will still give the segmentation fault error. I know this is because of a memory issue, just unsure of how to handle it

The file seems to get the segmentation fault from line 24

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int getFileInfo(const char *filename, float list[]);

int main(void)
{
float list[] = {0};
int size = getFileInfo("numbers.tsv4",list);
return 0;
}

int getFileInfo(const char *filename, float list[])
{
FILE* spData;
if((spData = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Error opening file %s.\n",filename);
exit(1);
}

int i = 0;
while(fscanf(spData, "%f", &list[i]) != EOF)
{
i++;
}

if (fclose(spData) == EOF)
{
fprintf(stderr, "Error closing file %s.\n", filename);
exit(2);
}
return i + 1;
}

Answer

The goal of the code is to store the unknown numbers into an array without knowing the amount of numbers in the file

In order to this read floats one by one and allocate the array on the heap.

When you write

float list[] = {0};
int size = getFileInfo("numbers.tsv4",list);

you allocate an array with one value on the stack and that can never change.

Instead pass a pointer to the function and let the function manipulate that pointer

float* list = NULL;
int size = getFileInfo("numbers.tsv4",&list);

Inside your function read the float values from the file and as the need increases realloc the list array E.g.

int size = 10; // lets start with 10 values
int readFloats = 0; // number of floats read
*list = malloc(sizeof(float)*size);

...

if (readFloats > size)
{
  float* tmp = realloc(*list, sizeof(float)*(size+10));
  if ( tmp != NULL )
  {
    size += 10;
    *list = tmp;
  }
  ... put in the float
}

At the end realloc again with the current number of floats to get the right size

 tmp = realloc(*list, readCurrent*sizeof(float));
 if ( tmp != NULL )
  {
    size = readCurrent;
    *list = tmp;
  }

...

Comments