2014-09-06 66 views
-1

它只是一個程序,我試圖讀取作爲下一個參數傳遞的文件中作爲參數傳遞的單詞的出現次數。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

回答

1

隨着對文件結尾的檢查超出註釋,您實際上有一個無限循環,其中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