ocamldebug 中的调用堆栈是真正的调用堆栈,因此进行尾调用的函数不会出现在其中。这令人困惑。如何获得包含尾调用的回溯?
问问题
750 次
2 回答
8
最简单的方法是更改您的函数,使其不再是尾递归的。当我想要在异常中止程序时显示良好的回溯时,这就是我使用的(在这种情况下不需要 ocamldebug,在下面运行程序OCAMLRUNPARAM="b"
就足够了;文档)。
我个人的技术是将尾调用更改为
let result = <tail call> in result
Ocaml 主要在编写代码时对其进行编译,在这种情况下它很棒:编译器不会内联它,并且您会得到一个漂亮的回溯。当然,一旦发现错误,您就可以轻松移除这种去优化。(当你只有几个尾调用时,这很好用;如果你有很多尾调用,你可以将整个函数体包装成 a let result = <body> in result
,但我觉得它不太方便和清晰。)
如果您需要该函数仍然是尾调用(例如,您可能会耗尽操作系统设置的堆栈大小限制),您可以将此函数的调用堆栈具体化为数据结构,将
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 回答