2017-01-15 16 views
0

私はこのルールをyaccファイルに、別のC++ファイルをルールのアクションとして使用しています。 しかし.This以下print文で示すように、出力が期待されていないparser.y内のルールです:yaccは予期せぬ結果を出力します

RecordItem : IdentifierList ':' TypeDenoter 
      { 
       char * result = declareRecordItem ($1 , $3); 
       $$ = result; 
       printf(" >>> inside RecordItem >> : %s\n",result); 
      } 
      ; 

と、これは機能である「declareRecordItem」main.cppにファイル内:

char* declareRecordItem(std::vector<char* >* varList , char* type){ 
    string stm = " "; 
    string identifier; 
    for(int i=0 ; i < varList-> size() ; i++) 
    { 
     identifier= string((*varList)[i]) ; 
     symtab[identifier] = string(type); 
     stm = stm + " " + string(type); 
    } 
    char * result = (char*)stm.c_str(); 
    printf(">>> inside declareRecordItem >> : %s\n",result); 

    return result ; 
} 

declareRecordItem関数の出力は正しいですが、RecordItemルールに戻ったときには何も生成されないか、または奇妙なシンボルが表示されることがあります。何か案が !。

>>> inside declareRecordItem >> : i32 i32 
>>> inside RecordItem >> : 

答えて

0

declareRecordItem内部では、タイプstd::stringのローカル変数stmを作成し、値を返す:(char*)stm.c_str()を。

ただし、declareRecordItemが返されるとすぐにstmが終了し、stm.c_str()によって返されたポインタは無効になります。現在指しているメモリは、他のオブジェクトを保持するために再利用されている可能性があります。

ですから、文字列の値を保持したい場合は、あなたはずのいずれか

  • リターン効率のためにRVOに頼るstd::string自体、または
  • 動的オブジェクトを作成して返します(つまりnew std::string()を) 、または
  • 文字列バッファのCスタイルのコピーを作成します(つまり、strdup(stm.c_str())

両方後者の2つのケースでは、あなたはトンが必要になりますoコピーが完了したら手動でコピーを解放します。最初のケースでは、C文字列を保持する必要がある場合は、基本となるC文字列のコピーを作成する必要があります。

CとC++の文字列処理を混同すると混乱し、コードが混乱します。 C++を使うつもりならば、Cスタイルの文字列と同じ手動メモリ管理体制になりますが、全体を通してstd::string*を使うことをお勧めします。シンボルテーブルを持つコンパイラやその他のアプリケーションでは、文字列スキャナを使用していても、できるだけ早く文字列をシンボルテーブル(または不変のシンボル名のマップ)に入れてから、シンボルへの参照を渡しますまたはインターンされた名前)。その後、コンパイルの最後に保持されている文字列のリポジトリ全体を解放することができます。

+0

動的オブジェクトを作成すると、ポインタ型、つまりstring * stm = new new std :: string()となります。 。しかし、どのようにループの中でそのように追加するか? –

+0

'* stm = * stm +" "+ ...'または単に '* stm + =" "+ ...' – rici

+0

最後にもう一度質問してください。どのように文字列*をchar *に変換できますか? –

関連する問題