5

私は Bison & Flex を 1 か月ほど使用しています。

Flex Bison でメモリを解放する際に問題があります。私のコードは次のようになります。

 parser.l

 {DATE}      { yylval.str= strdup(yytext);
             pair<string,string> newpair = make_pair("DATE",yytext);
             myvector.push_back(newpair);
              return TOKEN_DATE ;}

これは、私の .l ファイルの例の 1 つです。yytext の値を yylval.str にコピーします。次に、そのコンテンツ (実際にはキー/値) を使用して新しいペアを作成し、bison のトークン日付を返します。私のパーサー .y は yyparse 以下です。何かがキャッチされると、それを印刷するだけです。

これで valgrind を実行しようとしましたが、strdup に関して複数のエラーが発生しました。この関数が malloc を使用することは知っていますが、FREE を使用する場所と時期がわかりません。

おそらく.yファイルにあると思いますが、どこですか?

 test:
      TOKEN_DATE                 { cout << $1 << endl; // here ? and what to free ?}

私はこれのすべてを本当に理解していません。単純で明確な説明をいただければ幸いです。

前もって感謝します、


編集:

次のようないくつかのことを試しました:

 test:
      TOKEN_DATE TOKEN_TOTO TOKEN_BLABLA { cout << $1 << endl; free($1); free($2);}
    | TOKEN_DATE test { cout << $1 << endl, free($1); }

正常にコンパイルおよび実行されているように見えますが、valgrind は strdup 関数に含まれる malloc に問題があると私に言います。しかし、flex ファイル内に free(yylval.str) を書くことはできません。この漏れの問題を解決する方法が本当にわかりません。

4

3 に答える 3

6

コピーした文字列が不要になったら解放する必要があります。かなり単純なケースでは、印刷後に free($1) できますが、パーサーがコピーされた文字列をデータ構造に挿入することがよくあります。その場合、そのデータ構造は malloc されたストレージの所有者になり、 free の呼び出しはデストラクタで実行されます。

他のリソース管理の問題と実際には違いはありません。所有者はリソースが不要になったときにそのリソースを解放する責任があるため、割り当てられたリソースの所有者を常に明確にする必要があります。

内部で行われているのはbison、セマンティック値のスタックを維持することです。それぞれのタイプYYSTYPE(つまり、「セマンティック タイプ」) は、 のタイプでもありyylvalます。トークンがスタックにシフトされると、スタックの一番上にbisonコピーyylvalされます。プロダクションに対応するアクションを実行する前に、プロダクション内bisonの各終端および非終端の意味値が 、 などとして知られるようにします$1($2これはコピーではありません。さまざまな$x記号は場所への参照に置き換えられます)。bisonスタック上。)

各アクションは疑似変数に値を格納するため、非終端記号にもセマンティック値があります$$。(アクションがこれを行わない場合、 の値$$は予測できませんが、まだ存在します。) アクションが終了した後、bison はスタックの一番上から$1, $2... の値を削除し、疑似変数$$をスタックの一番上。ポップされた値に対しては何もしないので、それらを解放したり破壊したりする必要がある場合は、アクション自体でこれを行う必要があります。

セマンティック値はナイーブにコピーされるため、セマンティック型には自明にコピーできない C++ オブジェクトを含めるべきではありません。

%union宣言を使用する場合、セマンティック型YYSTYPEはオブジェクトであり、各端末および非端末に適用されるユニオン タグを指定unionする必要があります。bisonその場合、$$すべてに$n正しい.tagものが自動的に追加され、アクションはいくらか型安全になります。

于 2014-03-20T14:23:43.597 に答える
2

フレックスマニュアルから:

21.3 yytextとメモリーに関する注意

flex が一致を見つけると、yytext は入力バッファー内の一致の最初の文字を指します。文字列自体は入力バッファの一部であり、個別に割り当てられません。yytext の値は、次に yylex() が呼び出されたときに上書きされます。つまり、yytext の値は、一致したルールのアクション内からのみ有効です。

したがって、make_pair は次のようにすべきではありませんか?

pair<string,string> newpair = make_pair("DATE",yylval.str);

その場合、ペアのメモリをクリーンアップするときに文字列を解放する必要があります。

于 2015-03-18T10:48:05.603 に答える
1

簡単な答えは、場合によります。使い終わったら、いつでもメモリを解放する必要があります。

より役立つ答え: メモリの割り当てをできるだけ少なくしてみてください。記憶がなければmalloc、記憶する必要はありませんfree。あなたが与える例では、日付でパターンマッチします。通常、日付はフォーマットを保持し、長さに上限があります。たとえば、フォーマット「yyyy/mm/dd」には 10 文字が含まれます。これが予想できる場合は、日付を保持する新しい文字列を作成する代わりに、静的サイズの文字配列yylvalchar date[10];.

于 2014-03-20T14:19:01.073 に答える