getc中的分段错误

问题描述:

它只是一个程序,我试图读取作为下一个参数传递的文件中作为参数传递的单词的出现次数。getc中的分段错误

代码如下所示:

#include <stdio.h> 

extern void exit(int); 

void main(int argc, char *argv[]) { 

    char C, buf[10]; 
    int count = 0, i = 0; 
    FILE *fp; 

    if (argc != 3) { 
     printf("Please provide proper args\n"); 
     exit(0); 
    } 
    fp = fopen(argv[2], "r"); 
    if(fp == NULL) { 
     printf("File couldn't be opened\n"); 
     exit(1); 
    } 
    else { 
      do { 
       while ((C = fgetc(fp)) && (C != ' ') ) { 
        //if (C == EOF) break; 
        buf[i] = C; 
        i++; 
       } 
      buf[i] = '\0'; 
       i = 0; 

       if (strcmp(argv[1], buf) == 0) count++; 
      } while (C != EOF); 
    } 
    close(fp); 
    printf("Total \"%s\" occurances is %d\n", argv[1], count); 

}   

GDB:

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7a925fd in getc() from /lib64/libc.so.6 
Missing separate debuginfos, use: debuginfo-install glibc-2.18-12.fc20.x86_64 

现在,如果我第一while后删除"if"语句之前的评论也不会出现段错误。该程序中唯一的一行是评论。

但是,如果是这样的话,那么我们肯定已经越过了getc部分,并进入了这段时间。我在想这个问题可能是在做strcmp。但为什么我在gdb中看到getc的错误。

+1

如果'fgetc'返回'EOF',则不应再读取更多内容,否则会导致未定义的行为。当你不检查'EOF'时你所做的是试图超出文件末尾的阅读。 – 2014-09-06 11:07:08

+1

还要注意,如果你想能够可靠地测试'EOF','C'需要'int',而不是'char'。 – 2014-09-06 11:09:08

+0

但它然后不会崩溃,如果我取消注释“/ /如果(C == EOF)中断;” – bluefoggy 2014-09-06 11:09:30

随着对文件结尾的检查超出注释,您实际上有一个无限循环,其中fgetc继续返回EOF但您从不检查它。这导致undefined behavior,因为你会写出远远超出buf阵列的界限。可能发生的是,然后您覆盖FILE指针fp,将下一个呼叫屏蔽到fgetc,以对无效的FILE指针进行操作。

同样如另一条评论所述,fgets返回int。你需要知道(char) EOF != (int) EOF

+0

但我有另一个做(外环)之后,这将不会导致我们超越EOF阅读。 – bluefoggy 2014-09-06 11:19:00

+0

@kingsdeb但是内部循环是无限的,如果你在外部循环中检查,内部循环永远不会退出,这并不重要。 – 2014-09-06 11:20:10

+0

谢谢,我明白了你的观点。我根本就没有考虑过那些线。 – bluefoggy 2014-09-06 11:30:49