Печать следов стопки - PullRequest
       7

Печать следов стопки

3 голосов
/ 29 сентября 2011

У меня очень короткий тестовый файл:

let print_backtrace () = try raise Not_found with
    Not_found -> Printexc.print_backtrace stdout;;

let f () = print_backtrace (); Printf.printf "this is to make f non-tail-recursive\n";;

f ();

Я компилирую и запускаю:

% ocamlc -g test.ml      
% OCAMLRUNPARAM=b ./a.out
Raised at file "test.ml", line 1, characters 35-44
this is to make f non-tail-recursive

Почему f не указано в трассировке стека? Как я могу написать функцию, которая будет печатать трассировку стека местоположения, из которого она вызывается?

Ответы [ 2 ]

6 голосов
/ 29 сентября 2011

Документация для Printexc.print_backtrace гласит:

В обратном следе перечислены места программы, в которых было сгенерировано последнее возникшее исключение и где оно было распространено посредством вызовов функций.

Кажется, на самом деле все происходит правильно. Исключение не было распространено обратно через f.

Если я переместу вызов на Printexc.print_backtrace вне вызова на f, я увижу полную обратную трассировку.

$ cat test2.ml
let print_backtrace () = raise Not_found

let f () = let res = print_backtrace () in res ;;

try f () with Not_found -> Printexc.print_backtrace stdout
$ /usr/local/ocaml312/bin/ocamlc -g test2.ml
$ OCAMLRUNPARAM=b a.out 
Raised at file "test2.ml", line 1, characters 31-40
Called from file "test2.ml", line 3, characters 21-39
Called from file "test2.ml", line 5, characters 4-8
5 голосов
/ 29 сентября 2011

Вот код, чтобы сделать то, что я предложил.Я рекомендую использовать ocamldebug, если это вообще возможно, этот код слишком сложен.Но это работает на моей системе в этом простом примере.

let print_backtrace () =
    match Unix.fork () with
    | 0 -> raise Not_found
    | pid -> let _ = Unix.waitpid [] pid in ()

let f () =
    begin
    print_backtrace ();
    Printf.printf "after the backtrace\n";
    end

;;

f ()

Вот тестовый прогон.

$ /usr/local/ocaml312/bin/ocamlc unix.cma -g test3.ml
$ OCAMLRUNPARAM=b a.out
Fatal error: exception Not_found
Raised at file "test3.ml", line 3, characters 17-26
Called from file "test3.ml", line 8, characters 4-22
Called from file "test3.ml", line 14, characters 0-4
after the backtrace

Я понял, что из-за неперехваченного исключения у вас нетлюбой контроль над выходом дочернего процесса.Это одна из причин, по которой этот код слишком сложен.Пожалуйста, не вините меня, если он не работает для вас, но я надеюсь, что он окажется полезным.

Я протестировал код на Mac OS X 10.6.8, используя OCaml 3.12.0.

С наилучшими пожеланиями,

...