我需要在国外系统中调试一些模块, 模块有公共函数foo() - 我怎么知道位置(模块和函数名) 从哪个foo()给定模块被调用?我的意思是一堆电话。
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 :(得分:19)
这是一个简单的伎俩:
Trace = try throw(42) catch 42 -> erlang:get_stacktrace() end,
erlang:display(Trace)
答案 1 :(得分: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
的调用框已经存在。
答案 2 :(得分:1)
io:format("~s~n", [element(2, process_info(self(), backtrace))]).
self()可以被任何其他pid替换(rpc:pinfo甚至可以与远程procs一起使用)。如果您甚至无法修改源或光束,这将有所帮助。
答案 3 :(得分:1)
以下是我执行此操作的代码:
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模块。