• ベストアンサー

再帰のある関数で現在と同じレベルでのみ働くブレークポイントを定義する方法は?

Visual Studio 2005を使っております。 再帰を使った関数をデバッグしているのですが、ブレークポイントを指定すると再帰の深いところでブレークしてしまいます。現在実行しているのと同じ再帰のレベルでのみブレークさせるような方法は無いでしょうか? ご存知のかたがいらっしゃったら是非ご教授ください。

質問者が選んだベストアンサー

  • ベストアンサー
  • z64423
  • ベストアンサー率53% (26/49)
回答No.2

あんまりいい方法ではないですが、とりあえず… 再起関数内の最初の式あたり(関数先頭 = { の位置より後)にブレークポイントをセットして、条件として以下を指定します。 !((unsigned int)(eip - 0x40) <= *((unsigned int *)(ebp + 4)) && *((unsigned int *)(ebp + 4)) <= (unsigned int)(eip + 0x40)) EBP がフレームポインタなので、EBP+4 に戻りアドレス(呼び出し元関数)があります。 カッコ内の条件式は、EBP+4 (戻りアドレス)が再起関数内なら ture、他の関数から呼ばれた場合は false として、! で反転して再起関数以外から呼ばれたらブレークする、という意味です。 eip+0x40、eip-0x40 は調整してください。 テストに使ったサンプルを示します。 int recurs(int v) {   if (v++ < 10) {   // ここにブレークポイントをセット     v = recurs(v);   }   return v; } int _tmain(int argc, _TCHAR* argv[]) {   int v = 0;   printf("done : v=%d\n", recurs(v));   return 0; } ※このサンプルだと、(VS2005 Debug で)ビルドした場合に、再起呼び出し時の戻りアドレスは 0x004113F7 なので、ブレーク条件として *((unsigned int *)(ebp + 4)) != 0x004113F7 でも大丈夫だと思います。

moritan2
質問者

補足

ご回答ありがとうございます。 どうも、結論としてはスマートな方法はなくて、いろいろテクニックを使って実現するしかなうということですね。サンプルを参考にさせていただき、いろいろやってみます。 デバッガを設計したひとは、再帰的なプログラムのことは想定外だったのでしょうか? 昔からゲーム木の探索をしていると、絶対に欲しいと思っている機能なのですが。

すると、全ての回答が全文表示されます。

その他の回答 (1)

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.1

関数のつくりにもよるでしょうが、条件付ブレークポイントで何とかなりませんか。 # [デバッグ]->[ブレークポイント]

moritan2
質問者

補足

ご解答ありがとうございます。 たとえば、再帰レベルが増えるごとに1増えるような引数を再帰の関数に入れておいて、現在のこの変数の値をデバッガで別のグローバル変数にコピーして、引数がこのグローバル変数と等しいならばブレークする、ということですか? プログラムを変更しない方法は全く無いのでしょうか?

すると、全ての回答が全文表示されます。

関連するQ&A