堆栈溢出后如何在 OCaml 中获得完整的、未处理的堆栈跟踪?
How can I get a complete, untrucated stack trace in OCaml after a 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 "Whosebug.ml", line 6, characters 20-25
Called from file "Whosebug.ml", line 6, characters 20-25
…
Called from file "Whosebug.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 "Whosebug.ml", line 6, characters 20-35
Called from file "Whosebug.ml", line 5, characters 20-25
Called from file "Whosebug.ml", line 4, characters 20-25
Called from file "Whosebug.ml", line 3, characters 20-25
Called from file "Whosebug.ml", line 2, characters 20-25
Called from file "Whosebug.ml", line 1, characters 20-25
Called from file "Whosebug.ml", line 10, characters 2-7
如何防止 OCaml 截断堆栈跟踪?
当我重现你的结果时,我得到了 1024 行回溯,这是一个可疑的数字。
事实上,我看到该库在 byterun/caml/backtrace_prim.h:
中强加了 1024 的硬编码最大回溯大小
#define BACKTRACE_BUFFER_SIZE 1024
如果您想要更大的回溯,您可能必须构建一个新的标准库。
对于它的价值,我用 ocamlc 做了一点测试,当发生溢出时,我看到大约 262,000 个活动堆栈帧(使用默认堆栈大小)。
(使用 OCaml 4.04 的正确文件名进行编辑。)
您可以限制堆栈,使其不会溢出回溯缓冲区,例如(使用字节码测试)
$ 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
您可以使用 ocamldebug 获取堆栈跟踪:
ocamlc Whosebug.ml -o Whosebug
ocamldebug Whosebug
然后在 ocamldebug 中:
(ocd) run
[...]
Uncaught exception: Stack_overflow
(ocd) backstep
(ocd) bt
您可能希望将调试标志添加到 ocamlc (-g) 以在调试器中执行额外操作。
堆栈溢出的 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 "Whosebug.ml", line 6, characters 20-25
Called from file "Whosebug.ml", line 6, characters 20-25
…
Called from file "Whosebug.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 "Whosebug.ml", line 6, characters 20-35
Called from file "Whosebug.ml", line 5, characters 20-25
Called from file "Whosebug.ml", line 4, characters 20-25
Called from file "Whosebug.ml", line 3, characters 20-25
Called from file "Whosebug.ml", line 2, characters 20-25
Called from file "Whosebug.ml", line 1, characters 20-25
Called from file "Whosebug.ml", line 10, characters 2-7
如何防止 OCaml 截断堆栈跟踪?
当我重现你的结果时,我得到了 1024 行回溯,这是一个可疑的数字。
事实上,我看到该库在 byterun/caml/backtrace_prim.h:
中强加了 1024 的硬编码最大回溯大小#define BACKTRACE_BUFFER_SIZE 1024
如果您想要更大的回溯,您可能必须构建一个新的标准库。
对于它的价值,我用 ocamlc 做了一点测试,当发生溢出时,我看到大约 262,000 个活动堆栈帧(使用默认堆栈大小)。
(使用 OCaml 4.04 的正确文件名进行编辑。)
您可以限制堆栈,使其不会溢出回溯缓冲区,例如(使用字节码测试)
$ 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
您可以使用 ocamldebug 获取堆栈跟踪:
ocamlc Whosebug.ml -o Whosebug
ocamldebug Whosebug
然后在 ocamldebug 中:
(ocd) run
[...]
Uncaught exception: Stack_overflow
(ocd) backstep
(ocd) bt
您可能希望将调试标志添加到 ocamlc (-g) 以在调试器中执行额外操作。