2010-02-12 115 views
8

我需要在外部系統中調試某個模塊, 模塊具有公共函數foo() - 如何知道從哪個地方(模塊和函數名稱) foo()給定模塊被調用?我的意思是一堆電話。erlang調用堆棧

PS:我不能停止的系統,所有的工作,我可以通過重載做到這一點模塊(但SOM調試信息)

-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

我有修改我的例子,請註釋 – vinnitu 2010-02-12 16:34:32

+1

請注意,在上面的例子中,對給定:foo()的調用是尾部調用 - 這意味着堆棧上不會留下任何痕跡每個定義)。如果您需要進行這種調試,您應該瞭解有關Erlang的跟蹤。 – RichardC 2010-03-05 15:11:17

回答

17

這裏有一個簡單的一招:

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

這可能工作:

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

除了它不適用於尾部調用。例如,假設這兩個函數:

foo() -> 
    where_am_i(). 

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

我得到這些結果:

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}]} 

也就是說,我只能看到bar,因爲foo的調用框架已經離開時已經where_am_i被稱爲。

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

self()可以被任何其他pid替換(rpc:pinfo甚至可以與遠程procs一起工作)。如果你甚至不能修改源或光束,這將有所幫助。

0

這是我做這個代碼:

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). 

列表是系統中的自定義模塊。改用你的foo模塊。