2011-09-29 5 views
3

내가 매우 짧은 테스트 파일이 추적 :인쇄 스택은

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입니까? 호출 된 위치의 스택 추적을 인쇄하는 함수를 작성하려면 어떻게해야합니까?

답변

5

다음은 내가 제안한 코드입니다. 가능하다면 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 

캐치되지 않은 예외로 인해 자식 프로세스가 종료되는 방식을 제어 할 수 없다는 것을 깨달았습니다. 그것이이 코드가 너무 까다로운 이유 중 하나입니다. 제게 도움이되지 않는다면 나를 비난하지 마시고, 유용하다고 생각하길 바랍니다.

OCaml 3.12.0을 사용하여 Mac OS X 10.6.8에서 코드를 테스트했습니다.

감사합니다.

6

Printexc.print_backtrace에 대한 문서는 말한다 :

역 추적은 가장 최근에 발생한 예외가 발생한 프로그램의 위치를 ​​나열하고이 함수 호출을 통해 전파 된 곳.

사실 실제로 옳은 일을하고있는 것으로 보입니다. 예외는 f를 통해 다시 전파되지 않았습니다.

f 외의 Printexc.print_backtrace으로 전화를 이동하면 전체 백 트레이스가 표시됩니다.

$ 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 
+0

이 질문에 대한 답변은 절반입니다. 내가 원하는 것을 할 수 없다는 표시로서 나머지 절반에 침묵을 가져야 하는가? 즉, 전체 스택 추적을 인쇄하고 계속 진행할 것인가? –

+3

OCaml 런타임에서 해킹하지 않고 할 수있는 좋은 방법은 없습니다. 어쩌면 ocamldebug 아래에서 실행할 수 있습니까? 또는 어떤 종류의 유닉스에서 실행되고있는 것처럼 보이기 때문에 빠른 문제 해결을위한 것이라면 프로세스를 fork()하고 하위 프로세스에서 캐치되지 않는 예외를 발생시켜 전체 스택 추적을 인쇄 한 다음 하위 프로세스를 종료하고 상위 프로세스에서 계속하십시오. 나는 C 년 전에 이런 일을했고 그것은 나를 위해 일했습니다. 그러나 그것은 추악하고 무언가를 엉망으로 만드는 경향이 있습니다. 이 방법을 시도하면 (아마도 나쁜 생각 일 것입니다.) 자식에서 _Exit()을 호출하여 버퍼를 비우지 않게하십시오. 감사합니다, –

+0

네이티브 코드로 컴파일하면 스택을 인쇄하는 표준 함수를 사용할 수 있습니다. glibc의 libunwind 또는 backtrace. 결과가 매우 좋지는 않지만 대개 문제를 정확하게 지적 할 수 있습니다. – ygrek

관련 문제