Erlang 堆栈跟踪中包含多少条目?
How many entries are included in Erlang stack traces?
在查看 Erlang 程序错误的堆栈跟踪时,有时在我看来我没有看到全貌,一些条目已被删除。堆栈跟踪中包含的条目数是否有限制?
首先,如果堆栈跟踪作为 Erlang 术语打印,请注意如果列表足够深,io:format
可能会截断列表。如果发生这种情况,您将在输出中看到 ...
。
其次,如果堆栈跟踪中间似乎缺少条目,可能是因为尾调用优化。如果一个函数做的最后一件事是调用另一个函数,那么调用函数的堆栈帧将被消除,并且在堆栈跟踪中将不可见。
除此之外,只有最后(最里面的)八个 堆栈帧包含在堆栈跟踪中。例如,给定一个发出 12 帧深度错误信号的程序(请参见下面的列表),您将得到以下输出:
1> foo:one().
** exception error: this_is_twelve
in function foo:twelve/0 (foo.erl, line 49)
in call from foo:eleven/0 (foo.erl, line 45)
in call from foo:ten/0 (foo.erl, line 41)
in call from foo:nine/0 (foo.erl, line 37)
in call from foo:eight/0 (foo.erl, line 33)
in call from foo:seven/0 (foo.erl, line 29)
in call from foo:six/0 (foo.erl, line 25)
in call from foo:five/0 (foo.erl, line 21)
请注意,堆栈跟踪中不存在最外层的四个条目,仅保留最里面的八个条目。
八只是默认值。您可以通过使用 backtrace_depth
调用 erlang:system_flag/2
来更改它。 (它 returns 旧值。)
2> erlang:system_flag(backtrace_depth, 10).
8
3> foo:one().
** exception error: this_is_twelve
in function foo:twelve/0 (foo.erl, line 49)
in call from foo:eleven/0 (foo.erl, line 45)
in call from foo:ten/0 (foo.erl, line 41)
in call from foo:nine/0 (foo.erl, line 37)
in call from foo:eight/0 (foo.erl, line 33)
in call from foo:seven/0 (foo.erl, line 29)
in call from foo:six/0 (foo.erl, line 25)
in call from foo:five/0 (foo.erl, line 21)
in call from foo:four/0 (foo.erl, line 17)
in call from foo:three/0 (foo.erl, line 13)
这是foo.erl
。 x
原子在那里防止函数调用变成尾调用,这意味着调用者的堆栈帧将从堆栈跟踪中删除。
-module(foo).
-compile(export_all).
one() ->
two(),
x.
two() ->
three(),
x.
three() ->
four(),
x.
four() ->
five(),
x.
five() ->
six(),
x.
six() ->
seven(),
x.
seven() ->
eight(),
x.
eight() ->
nine(),
x.
nine() ->
ten(),
x.
ten() ->
eleven(),
x.
eleven() ->
twelve(),
x.
twelve() ->
error(this_is_twelve),
x.
在查看 Erlang 程序错误的堆栈跟踪时,有时在我看来我没有看到全貌,一些条目已被删除。堆栈跟踪中包含的条目数是否有限制?
首先,如果堆栈跟踪作为 Erlang 术语打印,请注意如果列表足够深,io:format
可能会截断列表。如果发生这种情况,您将在输出中看到 ...
。
其次,如果堆栈跟踪中间似乎缺少条目,可能是因为尾调用优化。如果一个函数做的最后一件事是调用另一个函数,那么调用函数的堆栈帧将被消除,并且在堆栈跟踪中将不可见。
除此之外,只有最后(最里面的)八个 堆栈帧包含在堆栈跟踪中。例如,给定一个发出 12 帧深度错误信号的程序(请参见下面的列表),您将得到以下输出:
1> foo:one().
** exception error: this_is_twelve
in function foo:twelve/0 (foo.erl, line 49)
in call from foo:eleven/0 (foo.erl, line 45)
in call from foo:ten/0 (foo.erl, line 41)
in call from foo:nine/0 (foo.erl, line 37)
in call from foo:eight/0 (foo.erl, line 33)
in call from foo:seven/0 (foo.erl, line 29)
in call from foo:six/0 (foo.erl, line 25)
in call from foo:five/0 (foo.erl, line 21)
请注意,堆栈跟踪中不存在最外层的四个条目,仅保留最里面的八个条目。
八只是默认值。您可以通过使用 backtrace_depth
调用 erlang:system_flag/2
来更改它。 (它 returns 旧值。)
2> erlang:system_flag(backtrace_depth, 10).
8
3> foo:one().
** exception error: this_is_twelve
in function foo:twelve/0 (foo.erl, line 49)
in call from foo:eleven/0 (foo.erl, line 45)
in call from foo:ten/0 (foo.erl, line 41)
in call from foo:nine/0 (foo.erl, line 37)
in call from foo:eight/0 (foo.erl, line 33)
in call from foo:seven/0 (foo.erl, line 29)
in call from foo:six/0 (foo.erl, line 25)
in call from foo:five/0 (foo.erl, line 21)
in call from foo:four/0 (foo.erl, line 17)
in call from foo:three/0 (foo.erl, line 13)
这是foo.erl
。 x
原子在那里防止函数调用变成尾调用,这意味着调用者的堆栈帧将从堆栈跟踪中删除。
-module(foo).
-compile(export_all).
one() ->
two(),
x.
two() ->
three(),
x.
three() ->
four(),
x.
four() ->
five(),
x.
five() ->
six(),
x.
six() ->
seven(),
x.
seven() ->
eight(),
x.
eight() ->
nine(),
x.
nine() ->
ten(),
x.
ten() ->
eleven(),
x.
eleven() ->
twelve(),
x.
twelve() ->
error(this_is_twelve),
x.