2016-10-25 20 views
2

私はファイルを語彙に分割するプログラムを作っていますが、私はCになじみがなく、奇妙なセグメンテーションエラーが発生しています。次のコードが実行され、印刷物:単純な割り当てによってセグメンテーションフォルトが発生する可能性はありますか?

1 
2 
Segmentation Fault: 11 

私は障害をセグメンテーションするために他の原因を調べていると私は2は私が間違って何をやっているの後、アレイには何もやっていませんよ?単純な割り当てによってセグメンテーションフォルトが発生する可能性はありますか?

#include <stdio.h> 

#define CHAR_CODE 1 
#define NUM_CODE 2 
#define RESERVED_CHAR_CODE 3 
#define SPACE_CODE 4 
#define ERR_CODE 5 

char token[16]; 
char line[128]; 
int lineLen = 0; 
int counter = 0; 
FILE *file; 

void cleanToken(){ 
    for(int i = 0 ; i < 16; i++){ 
     token[i] = 0; 
    } 
} 

void cleanLine(){ 
    for(int i = 0 ; i < 128; i++){ 
     line[i] = 0; 
    } 
} 

void next(){ 
    cleanToken(); 
    printf("1\n"); 
    char c; 
    if(counter == lineLen){ 
     printf("2\n"); 
     lineLen = 0; 
     printf("3"); 
     cleanLine(); 
     printf("4"); 
     counter = 0; 
     while((c=getc(file)) != 10 && c != EOF){ 
      if(c!=32){ 
       line[lineLen] = c; 
       lineLen++; 
      } 
      printf("%d\n", lineLen); 
     } 
     printf("%s\n", line); 
    } 
    c = line[counter]; 
    int type = getType(c); 
    while(getType(c)==type){ 
     token[counter] = c; 
     counter = counter + 1; 
     c = line[counter]; 
     if(c == EOF | c == 4 | type == RESERVED_CHAR_CODE){ 
      break; 
     } 
    } 
} 

int getType(int c){ 
    if((c > 96 & c < 123) | (c>64 & c < 91)){ 
     return CHAR_CODE; 
    } else if(c < 58 & c > 46){ 
     return NUM_CODE; 
    } else if(c == 32){ 
     return SPACE_CODE; 
    } else if(c == 33 | c == 34 | (c > 36 & c < 44) | c == 45 | c == 47 | (c > 58 & c < 63)){ 

     return RESERVED_CHAR_CODE; 
    } else { 
     return ERR_CODE; 
    } 
} 

int main(){ 
    int c; 
    FILE* file; 
    file = fopen("test.txt", "r"); 
    for(int i = 0; i < 10 ;i++){ 
     next(); 
     printf("%s\n", token); 
    } 
    return 0; 
} 
+1

すべての警告を有効にしてコンパイルします。 –

+1

あなたの 'test.txt'ファイルには何がありますか? –

+0

あなたのコードをインデントしてください。最小限の例を教えてください。そういう単純なprintfステートメントのsegフォールトは、通常、あなたの 'token'が正しくヌル終了しないことを意味します。 –

答えて

7

はしていないグローバル変数fileに、アクセスしようとすることで、コンパイル時に-Wallを使用して表示されますが、具体的には、クラッシュが発生しているほとんどがあなたのコード内の問題の数があります初期化されました。

main()に同じ名前の別の変数を使用してシャドウしました。あなたはそれを初期化しましたが、グローバルなものはnext()によってアクセスされていません。

また、printfステートメントはデバッグには不十分です。プログラムがクラッシュする前に出力バッファがコンソールにフラッシュされる保証はないためです。 をprintf("3") and printf("4")行に追加すると、クラッシュ前に印刷されることがわかります。また、printf()コールの後にfflush(stdout)に電話して、それらが印刷されていることを確認することもできます。こうすることで、表示された割り当ての結果としてクラッシュが発生していないことがわかります。

gdbなどのデバッガは、コードのデバッグに非常に役立ちます。

3

EDIT

DERP。ちょうどeddiemの答えを見て、彼は正しい - それはあなたのコードの本当の問題です。

ただし、ループにlineLenチェックを追加する必要があります。

ORIGINAL

ゴナ問題はここにある実際のお金を賭け:

ファイルは、単一の行に128の以上の文字が含まれている場合はどうなり
while((c=getc(file)) != 10 && c != EOF){ 
    if(c!=32){ 
     line[lineLen] = c; 
     lineLen++; 
    } 

?配列の終わりを過ぎて書くと、すべての種類の騒乱を引き起こす可能性があります。

あなたはあなたの配列の範囲を超えていないことを確認するためのチェックを追加する必要があります。

while (lineLen < 128 && (c = getc(file)) != 10 && c != EOF) { ... } 

あなたが34プリントアウト見ていないあなたがそれらのprintfに改行を持っていないので、ステートメント。 stdoutは、通常、行バッファリングされます。つまり、バッファがいっぱいになったり、改行文字が送信されたりしない限り、出力は端末に表示されません。

2

main関数では、2つの異なるfile変数があります。グローバル変数はプログラムの先頭に1つ、グローバル変数は1つです。

そして、next関数では、決して割り当てられていないグローバルfile関数を使用します。

#include <stdio.h> 
... 
FILE *file; // <<< global one 
... 


int main() { 
    int c; 
    FILE* file; // <<<local one 

    file = fopen("x.txt", "r"); 
    ... 
    return 0; 
} 

なぜグローバル変数を悪用すると問題につながるのかを示すもう1つの例です。

その他の問題が考えられます。