2017-01-13 11 views
-1

私は以下のコードのために(コアダンプ)セグメンテーションフォールトを取得しています:以下のlex/yaccファイルでセグメンテーションフォルト(コアダンプ)が受信されました。何が問題なの?

次のようにlexのファイルがあり、 test.l:次のように

%{ 

    #include "y.tab.h" 

    #define LOOKUP 0 

    int state; 

    int add_word(int type, char *word); 
    int lookup_word(char *word); 
    %} 

    %% 

    \n {state = LOOKUP;} 
    \.\n {state = LOOKUP; 
      return 0; 
     } 

    ^verb {state = VERB;} 
    ^adj {state = ADJECTIVE;} 
    ^adv {state = ADVERB;} 
    ^noun {state = NOUN;} 
    ^prep {state = PREPOSITION;} 
    ^pron {state = PRONOUN;} 
    ^conj {state = CONJUNCTION;} 

    [a-zA-Z]+ { 
       if(state != LOOKUP){ 
        add_word(state, yytext); 
       }else{ 
        switch(lookup_word(yytext)){ 
         case VERB: return(VERB); 
         case ADJECTIVE: return(ADJECTIVE); 
         case ADVERB: return(ADVERB); 
         case NOUN: return(NOUN); 
         case PREPOSITION: return(PREPOSITION); 
         case PRONOUN: return(PRONOUN); 
         case CONJUNCTION: return(CONJUNCTION); 
         default: 
          printf("%s: don't recog\n",yytext); 
        } 
       } 
       } 
    . ; 

    %% 
    struct word{ 
     char *word_name; 
     int word_type; 
     struct word *next; 
    }; 

    struct word *word_list; 

    extern void *malloc(); 

    int add_word(int type, char *word){ 
     struct word *wp; 
     if(lookup_word(word) != LOOKUP){ 
      printf("word %s already defined\n", word); 
      return 0; 
     } 

     wp = (struct word *) malloc(sizeof(struct word)); 

     wp-> next = word_list; 

     wp-> word_name = (char*) malloc(strlen(word)+1); 
     strcpy(wp->word_name, word); 
     wp->word_type = type; 
     word_list = wp; 
     return 1; 
    } 

    int lookup_word(char *word){ 
     struct word *wp = word_list; 

     for(; wp; wp = wp->next){ 
     if(strcmp(wp->word_name, word) == 0) 
      return wp->word_type; 
     } 
     return LOOKUP; 
    } 

のyaccファイルが

、あります

test.y:

%{ 

#include <stdio.h> 

%} 

%token NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION CONJUNCTION 

%% 
sentence: subject VERB object {printf("sentence is valid\n");} 
     ; 

subject: NOUN 
     | PRONOUN 
     ; 
object: NOUN 
     ; 

%% 

extern FILE *yyin; 

main(){ 
    while(!feof(yyin)){ 
     yyparse(); 
    } 
} 

yyerror(s) 
{ 
    fprintf(stderr, "some error\n"); 
} 

私は問題が何であるかを把握する時間しようとしてきました。私はこれらを完全に新しくしており、 "O'reilly - Lex and Yacc"という本に続いています。

+4

独自の標準関数のプロトタイプ宣言を提供しないでください。代わりに正しいヘッダーファイルを含めてください。また、[mallocの結果をキャストするこのディスカッション](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)も読んでください。 –

+4

http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – melpomene

+1

あなたの問題については、デバッガで実行した場合、クラッシュはどこで起こりますか?あなたのコードはコールスタックにありますか?また、質問を編集して、クラッシュを引き起こすために入力した情報を含めてください。 –

答えて

1

入力を行うための責任を負うコンポーネントである(F)LEX、によって生成されたスキャナは、その初期化関数の間、それぞれ、stdinstdoutyyinyyoutを初期化します。その前に、Cの静的初期化ルール(グローバルポインタ変数はNULLに初期化されています)の結果、両方ともNULLポインタになります。yylexが呼び出されたときに、初期化関数が呼び出されます。 (yylex次の呼び出しは、再び初期化をしないように、それはフラグを設定することは、ライブラリ・システムを初期化するには非常に一般的なアプローチです;最もmalloc実装とC stdio機能のいくつかの実装は、同じことを行う。)

yylexyyparseで繰り返し呼び出されるため、最初にyyparseを呼び出すと、暗黙的にyylexが呼び出されます。しかし、あなたが書くとき:それは初期化されている前

main(){ 
    while(!feof(yyin)){ 
    yyparse(); 
    } 
} 

yyinの最初の使用が発生しました。その結果、最初にwhileの状態が評価されると、yyinはまだNULLなので、2回目はありません。結果として生じるセグメンテーションは致命的です。

あなたはyyinを自分で初期化することによってこれを修正できますが、while (!feof(file))は常に間違っている(SM)であるので、ループの最後でEOFのテストを置くために、より理にかなって:

int main(){ 
    do yyparse(); while (!feof(yyin)); 
} 

質問this very helpful SO answerを参照してくださいなぜ "while (!feof (file))"は常に間違っていますか?詳細な分析についてはを参照してください。

+0

ありがとう!それは今より意味をなさない:D – user3470048

関連する問題