Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get a stack trace with tail calls included in Ocaml?

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?

like image 390
Robin Green Avatar asked Sep 03 '11 17:09

Robin Green


Video Answer


1 Answers

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.

like image 197
gasche Avatar answered Sep 26 '22 20:09

gasche