Ber*_*son 7 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);
}
Run Code Online (Sandbox Code Playgroud)
fgetsNULL如果它无法读取任何字符,则返回,如果您的文件包含少于LISTS行,则会发生这种情况.尝试printfNULL指针是未定义的行为.
这是一个提醒自己未定义行为确实未定义的好时机.它看起来printf应该是第一次崩溃.但是,C规范没有说明应该发生什么,所以你printf只是打印(null)(例如,很多Linux libcs都这样做).
为什么第二次 printf崩溃呢?这是因为你使用了这种模式
printf("%s\n", lists[i]);
Run Code Online (Sandbox Code Playgroud)
许多编译器会优化它
puts(lists[i]);
Run Code Online (Sandbox Code Playgroud)
并在系统中,puts并没有检查NULL指针,所以它出现segfaults.
故事的道德启示?不要依赖未定义的行为,甚至期望一致的结果.