堆栈溢出后,如何在OCaml中获得完整的,未经编译的堆栈跟踪?

时间:2017-04-05 04:29:33

标签: debugging ocaml stack-overflow

堆栈溢出的OCaml堆栈跟踪被截断;例如,以下程序生成如下所示的堆栈跟踪:

let rec f0 () = 1 + f1 ()
    and f1 () = 1 + f2 ()
    and f2 () = 1 + f3 ()
    and f3 () = 1 + f4 ()
    and f4 () = 1 + f5 ()
    and f5 () = 1 + f5 ()

let _ =
  Printexc.record_backtrace true;
  f0 ()
Fatal error: exception Stack overflow
Raised by primitive operation at file "stackoverflow.ml", line 6, characters 20-25
Called from file "stackoverflow.ml", line 6, characters 20-25
…
Called from file "stackoverflow.ml", line 6, characters 20-25

当错误堆栈溢出时将堆栈跟踪对比(将最终f5 ()更改为failwith "Oops"

Fatal error: exception Failure("Oops")
Raised at file "pervasives.ml", line 30, characters 22-33
Called from file "stackoverflow.ml", line 6, characters 20-35
Called from file "stackoverflow.ml", line 5, characters 20-25
Called from file "stackoverflow.ml", line 4, characters 20-25
Called from file "stackoverflow.ml", line 3, characters 20-25
Called from file "stackoverflow.ml", line 2, characters 20-25
Called from file "stackoverflow.ml", line 1, characters 20-25
Called from file "stackoverflow.ml", line 10, characters 2-7

如何阻止OCaml截断堆栈跟踪?

3 个答案:

答案 0 :(得分:4)

当我重现你的结果时,我会得到1024行回溯,这是一个可疑数字。

事实上,我看到该库在byterun / caml / backtrace_prim.h中强加了1024的硬编码最大回溯大小:

#define BACKTRACE_BUFFER_SIZE 1024

如果你想要更大的回溯,你可能需要建立一个新的标准库。

为了它的价值我用ocamlc进行了一些测试,当发生溢出时,我看到大约262,000个活动堆栈帧(默认堆栈大小)。

(使用正确的OCaml 4.04文件名编辑。)

答案 1 :(得分:2)

您可以限制堆栈,使其不会溢出回溯缓冲区,例如(用字节码测试)

$ env OCAMLRUNPARAM=b,l=1000 ./test
[...]
Called from file "test.ml", line 6, characters 20-25
Called from file "test.ml", line 6, characters 20-25
Called from file "test.ml", line 5, characters 20-25
Called from file "test.ml", line 4, characters 20-25
Called from file "test.ml", line 3, characters 20-25
Called from file "test.ml", line 2, characters 20-25
Called from file "test.ml", line 1, characters 20-25
Called from file "test.ml", line 10, characters 2-7

答案 2 :(得分:2)

您可以使用ocamldebug获取堆栈跟踪:

ocamlc stackoverflow.ml -o stackoverflow
ocamldebug stackoverflow

然后在ocamldebug:

(ocd) run
 [...] 
 Uncaught exception: Stack_overflow
(ocd) backstep
(ocd) bt

您可能希望将调试标志添加到ocamlc(-g)以在调试器中执行额外的操作。