简体   繁体   中英

Why is fscanf() seg faulting while trying to read from a file?

I am using C in Visual Studio via a remote Linux server. I want to read a file and store the contents in a array of structs. Every time I try to read a line using fscanf() it seg faults. Thanks in advance.

Format of the file I'm trying to read:

F150    5.4 28000 white
RAM1500 5.7 32000 orange
car     4.5 12000 green
truck   6.1 55000 black

Here's a simplified version my program as the other parts function fine:

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

struct data {
    char name[20];
    float floatNum;
    int intNum;
    char color[20];
} temp;

int scan(void) {
    int size = 0;
    FILE *data;
    data = fopen("./hw3.data", "r");
    while (1) {
        fscanf(data, "%s %f %d %s", temp.name, &temp.floatNum,
               &temp.intNum, temp.color);
        if (feof(data))
            break;
        size++;
    }
    return size;
}

void load(int size, struct data autos[]) {
    int i;
    FILE *data;
    data = fopen("./hw3.data", "r");
    for (i = 0; i < size; i++) {
        fscanf(data, "%s %f %d %s", autos[i].name, &autos[i].floatNum,
               &autos[i].intNum, autos[i].color);
    }
}

int main() {
    int size;
    struct data *autos;
    size = scan();
    autos = malloc(size * sizeof(struct data));
    load(size, autos);
    return 0;
}

There are multiple possible causes for problems:

  • you do not test if fopen() succeeds: if the file cannot be opened, the FILE pointer data will be null, causing undefined behavior in fscanf() , possibly a seg fault.

  • you do not test if malloc succeeds... again causing a seg fault if memory cannot be allocated.

  • you should close the FILE after reading

  • your test for feof() is incorrect: it might be true after successfully reading the last item, causing it to be ignored and you might never reach the end of file if one of the items cannot be read. You should just test the return value of fscanf() : it returns the number of successful conversions, so 4 in your case.

  • you should use %19s to avoid writing beyond the end of the targets arrays, another potential source of undefined behavior.

Here is a modified version:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct data {
    char name[20];
    float floatNum;
    int intNum;
    char color[20];
};

int scan(const char *filename) {
    struct data temp;
    int size = 0;
    FILE *data = fopen(filename, "r");
    if (data == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
        return -1;
    }
    while (fscanf(data, "%19s %f %d %19s",
                  temp.name, &temp.floatNum,
                  &temp.intNum, temp.color) == 4) {
        size++;
    }
    fclose(data);
    return size;
}

int load(const char *filename, int size, struct data autos[]) {
    int i;
    FILE *data = fopen(filename, "r");
    if (data == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
        return -1;
    }
    for (i = 0; i < size; i++) {
        if (fscanf(data, "%19s %f %d %19s",
                   autos[i].name, &autos[i].floatNum,
                   &autos[i].intNum, autos[i].color) != 4)
            break;
    }
    fclose(data);
    return i;
}

int main() {
    char filename[] = "./hw3.data";
    int size = scan(filename);
    if (size < 0)
        return 1;
    if (size > 0) {
        struct data *autos = malloc(size * sizeof(struct data));
        if (autos == NULL) {
            fprintf(stderr, "cannot allocate %zu bytes\n", size * sizeof(struct data));
            return 1;
        }
        int n = load(filename, size, autos);
        for (int i = 0; i < n; i++) {
            printf("%s %g %d %s\n", autos[i].name, autos[i].floatNum,
                   autos[i].intNum, autos[i].color);
        }
        free(autos);
    }
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM