5

ocamldebug のコール スタックは実際のコール スタックであるため、テール コールを行った関数は表示されません。これは紛らわしいです。末尾呼び出しを含むバックトレースを取得するにはどうすればよいですか?

4

2 に答える 2

8

最も簡単な方法は、関数を末尾再帰的でないように変更することです。これは、例外によってプログラムが中止されたときに適切なバックトレースを表示するときに使用するものです (この場合、ocamldebug は必要ありません。プログラムを実行するOCAMLRUNPARAM="b"だけで十分です。ドキュメント)。

私の個人的なテクニックは、テール コールを次のように変更することです。

let result = <tail call> in result

Ocaml はほとんどの場合、書かれているとおりにコードをコンパイルします。この場合は素晴らしいです。コンパイラはこれをインライン化せず、見栄えの良いバックトレースを取得します。もちろん、バグが見つかったら、この非最適化を簡単に削除できます。(テールコールが数回しかない場合、これは問題なく機能します。テールコールが多い場合は、関数本体全体を でラップできますがlet result = <body> in result、少し不便で明確ではありません。)

関数を引き続き末尾呼び出しにする必要がある場合 (たとえば、使い果たされる可能性がある OS 設定のスタック サイズ制限がある場合)、この関数の呼び出しスタックをデータ構造に具体化することができます。

let rec f arg1 arg2 .. argN =
  ...
  f arg1' arg2' .. argN'

の中へ

let rec f stack arg1 arg2 .. argN =
 let stack' = (arg1,arg2,..,argN)::stack in
 ...
  f stack' arg1' arg2' .. argN'

次に、ocamldebug でstack変数の値を調べて、関数固有のスタック トレースを取得できます。

于 2011-09-03T19:40:11.150 に答える
0

実際のテール コールがどこにあるかを確認するには、目的の呼び出し先に到達するまで「start」と繰り返し入力して逆実行し、スタックをポップしてから、バックステップします。手間がかかり、呼び出しごとに実行する必要がありますが、機能します。

于 2011-09-06T15:16:54.037 に答える