Skip to content

Commit fa9b575

Browse files
authored
Merge pull request #26960 from Liozou/outlining
Update stacktraces docs
2 parents b9f412b + 093bb0f commit fa9b575

File tree

1 file changed

+81
-88
lines changed

1 file changed

+81
-88
lines changed

doc/src/manual/stacktraces.md

Lines changed: 81 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ easy to use programmatically.
88
The primary function used to obtain a stack trace is [`stacktrace`](@ref):
99

1010
```julia-repl
11-
julia> stacktrace()
12-
4-element Array{StackFrame,1}:
13-
eval(::Module, ::Any) at boot.jl:236
14-
eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:66
15-
macro expansion at REPL.jl:97 [inlined]
16-
(::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:73
11+
6-element Array{Base.StackTraces.StackFrame,1}:
12+
top-level scope
13+
eval at boot.jl:317 [inlined]
14+
eval(::Module, ::Expr) at REPL.jl:5
15+
eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85
16+
macro expansion at REPL.jl:116 [inlined]
17+
(::getfield(REPL, Symbol("##28#29")){REPL.REPLBackend})() at event.jl:92
1718
```
1819

1920
Calling [`stacktrace()`](@ref) returns a vector of [`StackTraces.StackFrame`](@ref) s. For ease of use, the
@@ -25,9 +26,10 @@ julia> example() = stacktrace()
2526
example (generic function with 1 method)
2627
2728
julia> example()
28-
5-element Array{StackFrame,1}:
29+
7-element Array{Base.StackTraces.StackFrame,1}:
2930
example() at REPL[1]:1
30-
eval(::Module, ::Any) at boot.jl:236
31+
top-level scope
32+
eval at boot.jl:317 [inlined]
3133
[...]
3234
3335
julia> @noinline child() = stacktrace()
@@ -40,14 +42,14 @@ julia> grandparent() = parent()
4042
grandparent (generic function with 1 method)
4143
4244
julia> grandparent()
43-
7-element Array{StackFrame,1}:
45+
9-element Array{Base.StackTraces.StackFrame,1}:
4446
child() at REPL[3]:1
4547
parent() at REPL[4]:1
4648
grandparent() at REPL[5]:1
4749
[...]
4850
```
4951

50-
Note that when calling [`stacktrace()`](@ref) you'll typically see a frame with `eval(...) at boot.jl`.
52+
Note that when calling [`stacktrace()`](@ref) you'll typically see a frame with `eval at boot.jl`.
5153
When calling [`stacktrace()`](@ref) from the REPL you'll also have a few extra frames in the stack
5254
from `REPL.jl`, usually looking something like this:
5355

@@ -56,12 +58,14 @@ julia> example() = stacktrace()
5658
example (generic function with 1 method)
5759
5860
julia> example()
59-
5-element Array{StackFrame,1}:
61+
7-element Array{Base.StackTraces.StackFrame,1}:
6062
example() at REPL[1]:1
61-
eval(::Module, ::Any) at boot.jl:236
62-
eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:66
63-
macro expansion at REPL.jl:97 [inlined]
64-
(::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:73
63+
top-level scope
64+
eval at boot.jl:317 [inlined]
65+
eval(::Module, ::Expr) at REPL.jl:5
66+
eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85
67+
macro expansion at REPL.jl:116 [inlined]
68+
(::getfield(REPL, Symbol("##28#29")){REPL.REPLBackend})() at event.jl:92
6569
```
6670

6771
## Extracting useful information
@@ -72,17 +76,17 @@ default C functions do not appear in the stack trace), and an integer representa
7276
returned by [`backtrace`](@ref):
7377

7478
```julia-repl
75-
julia> top_frame = stacktrace()[1]
76-
eval(::Module, ::Expr) at REPL.jl:3
79+
julia> frame = stacktrace()[3]
80+
eval(::Module, ::Expr) at REPL.jl:5
7781
78-
julia> top_frame.func
82+
julia> frame.func
7983
:eval
8084
81-
julia> top_frame.file
82-
Symbol("./boot.jl")
85+
julia> frame.file
86+
Symbol("~/julia/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl")
8387
84-
julia> top_frame.line
85-
236
88+
julia> frame.line
89+
5
8690
8791
julia> top_frame.linfo
8892
MethodInstance for eval(::Module, ::Expr)
@@ -96,7 +100,7 @@ false
96100

97101
```julia-repl
98102
julia> top_frame.pointer
99-
0x00007f390d152a59
103+
0x00007f92d6293171
100104
```
101105

102106
This makes stack trace information available programmatically for logging, error handling, and
@@ -119,9 +123,10 @@ julia> @noinline example() = try
119123
example (generic function with 1 method)
120124
121125
julia> example()
122-
5-element Array{StackFrame,1}:
126+
7-element Array{Base.StackTraces.StackFrame,1}:
123127
example() at REPL[2]:4
124-
eval(::Module, ::Any) at boot.jl:236
128+
top-level scope
129+
eval at boot.jl:317 [inlined]
125130
[...]
126131
```
127132

@@ -147,7 +152,7 @@ julia> @noinline example() = try
147152
example (generic function with 1 method)
148153
149154
julia> example()
150-
6-element Array{StackFrame,1}:
155+
8-element Array{Base.StackTraces.StackFrame,1}:
151156
bad_function() at REPL[1]:1
152157
example() at REPL[2]:2
153158
[...]
@@ -174,7 +179,8 @@ grandparent (generic function with 1 method)
174179
175180
julia> grandparent()
176181
ERROR: Whoops!
177-
7-element Array{StackFrame,1}:
182+
10-element Array{Base.StackTraces.StackFrame,1}:
183+
error at error.jl:33 [inlined]
178184
child() at REPL[1]:1
179185
parent() at REPL[2]:1
180186
grandparent() at REPL[3]:3
@@ -183,77 +189,63 @@ ERROR: Whoops!
183189

184190
## Comparison with [`backtrace`](@ref)
185191

186-
A call to [`backtrace`](@ref) returns a vector of `Ptr{Cvoid}`, which may then be passed into
192+
A call to [`backtrace`](@ref) returns a vector of `Union{Ptr{Nothing}, Base.InterpreterIP}`, which may then be passed into
187193
[`stacktrace`](@ref) for translation:
188194

189195
```julia-repl
190196
julia> trace = backtrace()
191-
21-element Array{Ptr{Cvoid},1}:
192-
Ptr{Cvoid} @0x00007f10049d5b2f
193-
Ptr{Cvoid} @0x00007f0ffeb4d29c
194-
Ptr{Cvoid} @0x00007f0ffeb4d2a9
195-
Ptr{Cvoid} @0x00007f1004993fe7
196-
Ptr{Cvoid} @0x00007f10049a92be
197-
Ptr{Cvoid} @0x00007f10049a823a
198-
Ptr{Cvoid} @0x00007f10049a9fb0
199-
Ptr{Cvoid} @0x00007f10049aa718
200-
Ptr{Cvoid} @0x00007f10049c0d5e
201-
Ptr{Cvoid} @0x00007f10049a3286
202-
Ptr{Cvoid} @0x00007f0ffe9ba3ba
203-
Ptr{Cvoid} @0x00007f0ffe9ba3d0
204-
Ptr{Cvoid} @0x00007f1004993fe7
205-
Ptr{Cvoid} @0x00007f0ded34583d
206-
Ptr{Cvoid} @0x00007f0ded345a87
207-
Ptr{Cvoid} @0x00007f1004993fe7
208-
Ptr{Cvoid} @0x00007f0ded34308f
209-
Ptr{Cvoid} @0x00007f0ded343320
210-
Ptr{Cvoid} @0x00007f1004993fe7
211-
Ptr{Cvoid} @0x00007f10049aeb67
212-
Ptr{Cvoid} @0x0000000000000000
197+
18-element Array{Union{Ptr{Nothing}, Base.InterpreterIP},1}:
198+
Ptr{Nothing} @0x00007fd8734c6209
199+
Ptr{Nothing} @0x00007fd87362b342
200+
Ptr{Nothing} @0x00007fd87362c136
201+
Ptr{Nothing} @0x00007fd87362c986
202+
Ptr{Nothing} @0x00007fd87362d089
203+
Base.InterpreterIP(CodeInfo(:(begin
204+
Core.SSAValue(0) = backtrace()
205+
trace = Core.SSAValue(0)
206+
return Core.SSAValue(0)
207+
end)), 0x0000000000000000)
208+
Ptr{Nothing} @0x00007fd87362e4cf
209+
[...]
213210
214211
julia> stacktrace(trace)
215-
5-element Array{StackFrame,1}:
216-
backtrace() at error.jl:46
217-
eval(::Module, ::Any) at boot.jl:236
218-
eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:66
219-
macro expansion at REPL.jl:97 [inlined]
220-
(::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:73
212+
6-element Array{Base.StackTraces.StackFrame,1}:
213+
top-level scope
214+
eval at boot.jl:317 [inlined]
215+
eval(::Module, ::Expr) at REPL.jl:5
216+
eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85
217+
macro expansion at REPL.jl:116 [inlined]
218+
(::getfield(REPL, Symbol("##28#29")){REPL.REPLBackend})() at event.jl:92
221219
```
222220

223-
Notice that the vector returned by [`backtrace`](@ref) had 21 pointers, while the vector returned
224-
by [`stacktrace`](@ref) only has 5. This is because, by default, [`stacktrace`](@ref) removes
221+
Notice that the vector returned by [`backtrace`](@ref) had 18 elements, while the vector returned
222+
by [`stacktrace`](@ref) only has 6. This is because, by default, [`stacktrace`](@ref) removes
225223
any lower-level C functions from the stack. If you want to include stack frames from C calls,
226224
you can do it like this:
227225

228226
```julia-repl
229227
julia> stacktrace(trace, true)
230-
27-element Array{StackFrame,1}:
231-
jl_backtrace_from_here at stackwalk.c:103
232-
backtrace() at error.jl:46
233-
backtrace() at sys.so:?
234-
jl_call_method_internal at julia_internal.h:248 [inlined]
235-
jl_apply_generic at gf.c:2215
236-
do_call at interpreter.c:75
237-
eval at interpreter.c:215
238-
eval_body at interpreter.c:519
239-
jl_interpret_toplevel_thunk at interpreter.c:664
240-
jl_toplevel_eval_flex at toplevel.c:592
241-
jl_toplevel_eval_in at builtins.c:614
242-
eval(::Module, ::Any) at boot.jl:236
243-
eval(::Module, ::Any) at sys.so:?
244-
jl_call_method_internal at julia_internal.h:248 [inlined]
245-
jl_apply_generic at gf.c:2215
246-
eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:66
247-
ip:0x7f1c707f1846
248-
jl_call_method_internal at julia_internal.h:248 [inlined]
249-
jl_apply_generic at gf.c:2215
250-
macro expansion at REPL.jl:97 [inlined]
251-
(::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:73
252-
ip:0x7f1c707ea1ef
253-
jl_call_method_internal at julia_internal.h:248 [inlined]
254-
jl_apply_generic at gf.c:2215
255-
jl_apply at julia.h:1411 [inlined]
256-
start_task at task.c:261
228+
21-element Array{Base.StackTraces.StackFrame,1}:
229+
jl_apply_generic at gf.c:2167
230+
do_call at interpreter.c:324
231+
eval_value at interpreter.c:416
232+
eval_body at interpreter.c:559
233+
jl_interpret_toplevel_thunk_callback at interpreter.c:798
234+
top-level scope
235+
jl_interpret_toplevel_thunk at interpreter.c:807
236+
jl_toplevel_eval_flex at toplevel.c:856
237+
jl_toplevel_eval_in at builtins.c:624
238+
eval at boot.jl:317 [inlined]
239+
eval(::Module, ::Expr) at REPL.jl:5
240+
jl_apply_generic at gf.c:2167
241+
eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85
242+
jl_apply_generic at gf.c:2167
243+
macro expansion at REPL.jl:116 [inlined]
244+
(::getfield(REPL, Symbol("##28#29")){REPL.REPLBackend})() at event.jl:92
245+
jl_fptr_trampoline at gf.c:1838
246+
jl_apply_generic at gf.c:2167
247+
jl_apply at julia.h:1540 [inlined]
248+
start_task at task.c:268
257249
ip:0xffffffffffffffff
258250
```
259251

@@ -264,9 +256,10 @@ s by passing them into [`StackTraces.lookup`](@ref):
264256
julia> pointer = backtrace()[1];
265257
266258
julia> frame = StackTraces.lookup(pointer)
267-
1-element Array{StackFrame,1}:
268-
jl_backtrace_from_here at stackwalk.c:103
259+
1-element Array{Base.StackTraces.StackFrame,1}:
260+
jl_apply_generic at gf.c:2167
269261
270262
julia> println("The top frame is from $(frame[1].func)!")
271-
The top frame is from jl_backtrace_from_here!
263+
The top frame is from jl_apply_generic!
272264
```
265+

0 commit comments

Comments
 (0)