1

std::list<T>Metrowerks CodeWarrior デバッガーでSTL のデータを表示する簡単な方法はありますか? 次のような式を見ると、リストの先頭または末尾付近のデータを表示できます。

instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_.prev_->data_

構造体メンバーの横にある小さな「+」記号を展開して、一度に 1 要素ずつリストをたどることができますが、これは面倒です。約 20 ~ 30 要素を超えると、デバッガー ウィンドウに対してツリーが広すぎます。私が調べているリストには、2000 を超える要素があります。

CodeWarrior デバッガーは、式で関数を呼び出すことをサポートしていないため、(++(++instances.begin()))またはそのような値を調べることができません。非常に長くて不便な名前を持つ構造体メンバーしか見ることができません。

デバッガー ウィンドウも約 245 文字に制限されているため、N 番目のノードに展開される途方もなく長い式を生成するスクリプトを作成することはできません。

再現するのに数時間の浸漬が必要な問題をデバッグしようとしているので、コードを段階的に追加したり、再コンパイルしたり、再デバッグしたりする必要があるものは、あまり役に立ちません。しかし、他に選択肢がない場合は、そうしなければならないかもしれません。

4

3 に答える 3

1

これは間違いなく「簡単な方法」ではありません (「+」で行っている方法よりも簡単ではないかもしれません) が、場合によっては、watch ビューを扱うよりも便利だと思います。また、非常に悪い状況 (watch ビューが何らかの理由でほとんど機能しない場合、またはバイナリ メモリ ダンプ ファイルがある場合) でデバッグできる場合もあります。

std::list を使用すると、通常、メモリ内に次のような実装があります (詳細については、必要に応じて <list> を参照してください)。

構造体リスト
{
  ノード * 次;
  ノード * 前;
  size_t サイズ;
}

テンプレート
構造体ノード
{
  ノード * 次; // 最後のノードは別のノードではなくリストを指します
  ノード * 前; // 最初のノードは別のノードではなくリストを指します
  Tペイロード; // たとえば std::list では、これは Foo * ペイロードになります
}

実装では、next と prev の順序が逆になる場合があることに注意してください。

&myList は、ほとんどの実装で基本的に "end()" と同等です。

メモリ ビューを使用すると、&myList の近くをうろうろできます。これにより、myList.prev または myList.next ポインターの値を見つけ、メモリ ビューを変更してそれを確認できます。次に、リストの最後のノードまたは最初のノードにそれぞれ到達しました。

ノードに到達したら、前、次、またはペイロードを確認してから、前または次に移動できます。泡立てて、すすぎ、繰り返します。&myList に戻った場合は、すべてをトラバースしたことがわかります。

痛くて退屈?おそらく。しかし、stl の実装については十分に理解できます。場合によっては、可能性のあるストンプを簡単に「見る」ことができます。また、他のすべての可能性が窓から飛び出してしまうときにも役立つスキルです。

(どこに行ったかをメモしておいてください。混乱するのは本当に簡単です。)

于 2009-04-29T19:32:51.527 に答える
0

私が抱えていた問題は、リストに数千の要素があったという事実に起因していたことが判明しました。

この特定の STL 実装では、prevポインターは各ノードのオフセット 0 に格納されていたので、逆参照を繰り返すだけでリンクをたどることができました。次の怪物は、20 個のリンクを後方に見ています。

********************((Metrowerks::node_base**********************)instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_)

各逆参照の後に 4 バイトずつオフセットする必要があるため、前方リンクをたどるのはさらに醜いです。

于 2009-05-02T01:49:10.123 に答える
0

デバッガーは確かに、STL にはるかに適したものになる可能性があります。特に CodeWarrior については詳しくありませんが、デバッグ ウィンドウから関数をまったく呼び出せない場合はありますか? それとも、(1) プログラムが既に終了している場合は関数を呼び出すことができず (ABORT、segfault など)、(2) テンプレート展開を含む関数を呼び出すことができない、私が使用した他のデバッガーに似ていますか? (画像にコードを追加する必要があるかもしれません)が、(3)コードがブレークポイントで停止した場合、静的にリンクされた関数を呼び出すことができますか?

list<T>後者の場合、関心のある特定の型について、a を T の C スタイルの配列にコピーする 1 つ以上のテンプレート化されていない関数をコードに追加することをお勧めします。デバッグ ウィンドウでそれを実行してから、配列要素を調べてリストの内容を確認します。デバッグ ウィンドウから関数を呼び出すことができない場合は、コード内のエラー ポイントの近くにその関数への呼び出しをいくつか配置し、結果を確認する必要がある場合があります。可能であれば、これらの呼び出しを保護して、デバッグ フラグが設定されている場合にのみ呼び出されるようにします。

于 2009-05-01T18:15:00.417 に答える