2010-02-12 9 views
8

Ich muss einige Module im fremden System debuggen, Modul hat öffentliche Funktion foo() - Wie kann ich Ort (Modul und Funktionsname) von dem foo() gegeben Modul wurde genannt? Ich meine, Stapel von Anrufen.Erlang Aufrufstack

PS: Ich nicht System stoppen, alle Arbeit, die ich dieses Modul durch Neuladen tun können (aber mit som Debug-Informationen)

-module(given). 
-export(foo/0). 

foo() -> 
    %% here is my debug - and i need here(!) known about unknown_module:unknown_foo! 
    ok. 

--- 
-module(unknown_module). 
.. 

unknown_foo() -> 
    given:foo(). %% see above 
+0

Ich habe mein Beispiel geändert, bitte kommentiert – vinnitu

+1

Bitte beachten Sie, dass in einem Fall wie dem oben genannten Beispiel der Aufruf von: foo() ein Tail Call ist - das bedeutet, dass es keine Spur mehr auf dem Stack gibt (per Definition). Wenn Sie diese Art des Debuggens durchführen müssen, sollten Sie sich mit der Ablaufverfolgung in Erlang vertraut machen. – RichardC

Antwort

17

Hier ist ein einfacher Trick:

Trace = try throw(42) catch 42 -> erlang:get_stacktrace() end, 
erlang:display(Trace) 
2

Dies könnte funktionieren:

where_am_i() -> 
    try throw(a) 
    catch throw:a -> 
      erlang:get_stacktrace() 
    end. 

Außer, dass es nicht für Tail-Anrufe funktioniert. Zum Beispiel diese beiden Funktionen gegeben:

foo() -> 
    where_am_i(). 

bar() -> 
    X = where_am_i(), 
    {ok, X}. 

ich diese Ergebnisse:

4> foo:foo(). 
[{foo,where_am_i,0}, 
{erl_eval,do_apply,5}, 
{shell,exprs,6}, 
{shell,eval_exprs,6}, 
{shell,eval_loop,3}] 
5> foo:bar(). 
{ok,[{foo,where_am_i,0}, 
    {foo,bar,0}, 
    {erl_eval,do_apply,5}, 
    {shell,exprs,6}, 
    {shell,eval_exprs,6}, 
    {shell,eval_loop,3}]} 

Das heißt, ich kann nur bar sehen, da foo ‚s Aufrufrahmen bereits verlassen wurde, wenn where_am_i genannt wird .

1
 
io:format("~s~n", [element(2, process_info(self(), backtrace))]). 

selbst() kann durch eine andere ersetzt werden pid (rpc: pinfo auch mit Remote-Procs funktionieren sollte). Dies hilft, wenn Sie nicht einmal die Quelle oder den Strahl ändern können.

0

Hier ist mein Code, dies zu tun:

format_stack_entry(S) -> 
    {Module,Fun,Arity,[{file,File},{line,Line}]}=S, 
    io_lib:format("{~p,~p,~p,[{file,~p},{line,~p]}",[Module,Fun,Arity,File,Line]). 
stacktop([Top|_]) -> 
    Top. 
ancestor(N) -> 
    {_,Stacktrace}=erlang:process_info(self(),current_stacktrace), 
    ancestor(N+1,Stacktrace). 
ancestor(1,S) -> 
    format_stack_entry(stacktop(S)); 
ancestor(N,[_|T]) -> 
    ancestor(N-1,T). 

info(Format)  -> io:format(lists:concat([ancestor(2),Format,"\r"])). 
info(Format,Args) -> io:format(lists:concat([ancestor(2),Format,"\r"]),Args). 

Listen sind ein benutzerdefiniertes Modul in dem System ein. Verwenden Sie stattdessen Ihr foo-Modul.