第二次调用printf时出现分段错误

时间:2013-04-03 22:00:15

标签: c segmentation-fault

我正在编写一个打开文件的简单C程序,并将每一行读入一个数组,其中LISTS是我希望读取的文件中的最大行数。

然而,当MASTER_LIST小于LISTS行时,我第二次在printf()上得到分段错误,但不是第一次(我已经评论过显示在哪里)。

我对这种行为感到有些困惑,我想知道是什么导致它以及我可以做些什么来规避它。理想情况下,当fgets找到文件的结尾时,我会停止阅读。

#define MASTER_LIST "master_list.txt"
#define LINE 64
#define LISTS 32

char **lists = malloc(LISTS * sizeof(char *));
int i; 
for (i = 0; i < LISTS; i++) {
    lists[i] = malloc(LINE * sizeof(char));
}

/*Open the file for reading.*/
FILE *fp = fopen(MASTER_LIST, "r");
if (fp != NULL) {
    /*Each line of the file, up to LISTS is read into lists.*/
    for (i = 0; i < LISTS; i++){

        lists[i] = fgets(lists[i], LINE, fp);
        /*NO SEGFAULT HERE*/ printf("Line Read: %s\n", lists[i]);                   
    }
}

/*print out each line*/
for(i = 0; i < LISTS; i++){
    printf("Are we segfaulting yet? %d\n", i);
    /*HERE I GET A SEGFAULT*/ printf("%s\n", lists[i]);
    printf("How about now? %d\n", i);       
}

1 个答案:

答案 0 :(得分:9)

如果

fgets无法读取任何字符,则会返回NULL,如果您的文件包含少于LISTS行,则会发生这种情况。尝试printf NULL指针是未定义的行为。


这是一个提醒自己未定义行为确实未定义的好时机。看起来printf会导致第一次时间崩溃。但是,C规范没有说明应该发生什么,所以你的printf只打印(null)(例如,很多Linux libcs​​就这样做了。)

为什么第二次 printf会崩溃呢?这是因为你使用了模式

printf("%s\n", lists[i]);

许多编译器会将此优化为

puts(lists[i]);

在您的系统上,puts执行检查是否为NULL指针,因此会出现段错误。

故事的道德?不要依赖未定义的行为,甚至期望一致的结果。