The call stack in ocamldebug is the real call stack, so functions that have made a tail call don't show up in it. This is confusing. How can I get a backtrace that includes tail calls?
The easiest way is to change your function so that it is not tail-recursive anymore. This is what I use when I want good backtraces displayed when an exception aborts the program (no need for ocamldebug in this case, running the program under OCAMLRUNPARAM="b"
is enough; documentation).
My personal technique is to change the tail call into
let result = <tail call> in result
Ocaml mostly compile the code as it is written, and in this case it's great: the compiler doesn't inline this and you get a nice-looking backtrace. Of course you can easily remove this deoptimization once the bug is found.
(This works fine when you have only a few tail calls; if you have a lot of them, you can wrap the whole function body into a let result = <body> in result
, but I find it a bit less convenient and clear.)
If you need the function to still be taill-call (e.g., you have a OS-set stack size limit that you may exhaust), you could reify the call stack for this function into a data structure, turning
let rec f arg1 arg2 .. argN =
...
f arg1' arg2' .. argN'
into
let rec f stack arg1 arg2 .. argN =
let stack' = (arg1,arg2,..,argN)::stack in
...
f stack' arg1' arg2' .. argN'
Then you can, in a ocamldebug, examine the value of the stack
variable, to get a function-specific stack trace.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With