2010-02-12 25 views
8

Tôi cần gỡ lỗi một số mô-đun trong hệ thống nước ngoài, mô-đun có chức năng công cộng foo() - làm cách nào tôi có thể biết địa điểm (tên mô-đun và chức năng) mà từ đó foo() cho mô-đun được gọi? Tôi có nghĩa là chồng các cuộc gọi.erlang call stack

PS: Tôi không thể dừng lại hệ thống, tất cả công việc tôi có thể làm bằng cách tải lại mô-đun này (nhưng với som thông tin gỡ lỗi)

-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

Tôi sửa đổi ví dụ của mình, vui lòng nhận xét – vinnitu

+1

Xin lưu ý rằng trong trường hợp như ví dụ trên, lệnh gọi: foo() là cuộc gọi đuôi - điều này có nghĩa là sẽ không còn dấu vết nào trên ngăn xếp (theo định nghĩa). Nếu bạn cần thực hiện loại gỡ lỗi này, bạn nên tìm hiểu về truy tìm trong Erlang. – RichardC

Trả lời

17

Dưới đây là một thủ thuật đơn giản:

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

này có thể làm việc:

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

Ngoại trừ việc nó không hoạt động cho các cuộc gọi đuôi. Ví dụ, với hai chức năng:

foo() -> 
    where_am_i(). 

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

tôi nhận được những kết quả này:

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

Đó là, tôi chỉ có thể nhìn thấy bar, vì foo 's khung cuộc gọi đã được để lại đã khi where_am_i được gọi là .

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

self() có thể được thay thế bằng bất kỳ pid nào khác (rpc: pinfo thậm chí nên hoạt động với procs từ xa). Điều này giúp nếu bạn thậm chí không thể sửa đổi nguồn hoặc chùm.

0

Đây là mã của tôi để làm điều này:

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

Lists là một mô-đun tùy chỉnh trong hệ thống. Sử dụng mô-đun foo của bạn để thay thế.