为什么这个fscanf()在使用大文件时会出现段错误?

时间:2014-12-09 23:09:40

标签: c file linked-list eof scanf

我有一个函数接收文件名作为参数。 我们的想法是读取给定文件中的每个单词并将每个单词保存在链表中(作为带有值的结构和指向下一个结构的指针)。 我可以让它适用于小文件,但是当我提供一个大的.txt文件时,我会遇到分段错误。 使用gdb我可以发现这发生在while(fscanf(fi, "%s", value) != EOF){行。 出于某种原因,当文件较大时,fscanf()会出现段错误。 我可以弄清楚链接列表部分,在这里我粘贴了足够的代码来编译并让你看到我的问题。

所以我的问题是: 为什么fscanf()segfauts有大的.txt文件(数千个单词),而不是小文件(10个单词)?

顺便问一下,有没有更好的方法来检查文件的结尾?

提前致谢。

bool read(const char* file){
    // open file
    FILE* fi = fopen(file, "r"); //file is a variable that contains the name of the file to be opened
    if (fi == NULL)
    {
        return false;
    }

    // malloc for value
    char* value = malloc(sizeof(int));

    // fscanf() until the end of the file
    while(fscanf(fi, "%s", value) != EOF){ // HERE IS MY PROBLEM
        // some code for the linked list
        // where the value will be saved at the linked list
    }

    // free space
    free(value);

    // close the file
    fclose(fi);

    return true;
}

2 个答案:

答案 0 :(得分:1)

不,这是你的问题:

 char* value = malloc(sizeof(int));   //  <<<<<<< You allocate only place for an int 

 while(fscanf(fi, "%s", value) != EOF){ // <<<<<<< but you read a huge string 

所以你最终会出现缓冲区溢出!

您必须通过设置一些限制来确保永远不会超出缓冲区的大小。例如,通过使用fscanf()的宽度字段来指示要为字符串读取的字符的最大大小:

 char* value = malloc(512);   // Allocate your buffer 
 while(fscanf(fi, "%511s", value) != EOF){ // read max 511 chars + 1 char for terminating 0  
    ...

答案 1 :(得分:1)

(免责声明:简化说明)

char*是指向内存地址的指针。它指定它指向一个字符数组。 malloc调用会保留一定大小的内存块。

你的行

char* value = malloc(sizeof(int));

创建一个可以容纳4个字符的字符数组(因为int通常是4个字节长)。并且为了使它成为一个完整的字符串,最后一个字符必须是一个NULL终止符&#39; \ 0&#39;,所以它实际上只能容纳3个可读字符。

你应该让malloc创建一个大于文件中最大字符串的内存块。或者您可以使用其他更安全的方法,例如fgetshttp://www.cplusplus.com/reference/cstdio/fgets/