Program app.rb
:
def foo(msg)
result = bar
msg
end
def bar
thing = 123
thing
end
require "debug" # this is what drops us into the debugger
p foo(:hai)
Run the program as normal:
ruby app.rb
We find ourselves not necessarily where we’d expect:
Debug.rb
Emacs support available.
/Users/M/.rbenv/versions/2.1.2/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:57: RUBYGEMS_ACTIVATION_MONITOR.enter
(rdb:1)
So first thing to do is to check for any breakpoints:
b
=> No breakpoints
Let’s set a breakpoint for our foo
method (e.g. whenever it’s called we’ll stop there):
b app.rb:foo
=> Set breakpoint 1 at app.rb:foo
Let’s check the breakpoint was set:
b
=> Breakpoints:
1 app.rb:foo
Let’s also set a breakpoint within the foo
method at line 3
(just after we call the bar
method and assign its result to result
):
b app.rb:3
=> Set breakpoint 2 at app.rb:3
Again, let’s check the breakpoint was set:
b
=> Breakpoints:
1 app.rb:foo
2 app.rb:3
Let’s remind ourselves where we are before continuing on:
w
=> #1 /Users/M/.rbenv/versions/2.1.2/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:57:in `require'
If we forget any debugging commands we can look at the help:
h
=> Debugger help v.-0.002b
Commands
b[reak] [file:|class:]<line|method>
b[reak] [class.]<line|method>
set breakpoint to some position
wat[ch] <expression> set watchpoint to some expression
cat[ch] (<exception>|off) set catchpoint to an exception
b[reak] list breakpoints
cat[ch] show catchpoint
del[ete][ nnn] delete some or all breakpoints
disp[lay] <expression> add expression into display expression list
undisp[lay][ nnn] delete one particular or all display expressions
c[ont] run until program ends or hit breakpoint
s[tep][ nnn] step (into methods) one line or till line nnn
n[ext][ nnn] go over one line or till line nnn
w[here] display frames
f[rame] alias for where
l[ist][ (-|nn-mm)] list program, - lists backwards
nn-mm lists given lines
up[ nn] move to higher frame
down[ nn] move to lower frame
fin[ish] return to outer frame
tr[ace] (on|off) set trace mode of current thread
tr[ace] (on|off) all set trace mode of all threads
q[uit] exit from debugger
v[ar] g[lobal] show global variables
v[ar] l[ocal] show local variables
v[ar] i[nstance] <object> show instance variables of object
v[ar] c[onst] <object> show constants of object
m[ethod] i[nstance] <obj> show methods of object
m[ethod] <class|module> show instance methods of class or module
th[read] l[ist] list all threads
th[read] c[ur[rent]] show current thread
th[read] [sw[itch]] <nnn> switch thread context to nnn
th[read] stop <nnn> stop thread nnn
th[read] resume <nnn> resume thread nnn
pp expression evaluate expression and pretty_print its value
p expression evaluate expression and print its value
r[estart] restart program
h[elp] print this help
<everything else> evaluate
Let’s just ‘continue’ to our first breakpoint (which should be the foo
method being called):
c
=> Breakpoint 1, foo at app.rb:foo
app.rb:1:def foo(msg)
To be sure where we are let’s use l
again:
l
[-4, 5] in app.rb
=> 1 def foo(msg)
2 result = bar
3 msg
4 end
5
If at this point I enter the expression msg
(which is the argument incoming into the foo
method), then I’ll get its value:
msg
=> :hai
If I press c
to continue again we’ll reach our next breakpoint:
c
=> Breakpoint 2, foo at app.rb:3
app.rb:3: msg
If at this point I enter the expression result
(which is the variable set within the foo
method), then I’ll get its value that was provided by the bar
method:
result
=> 123
I can check for any local variables scoped/available to me at this point of the program:
v l
msg => :hai
result => 123
Before we wrap up, let me restart the program so we can go through the process again but take a slightly different route:
r
=> app.rb:57:
Note: the line number
57
doesn’t actually make any sense to me to be honest
From here we can ‘continue’ c
to get to our first breakpoint (like we did before), but this time instead of skipping over the call to bar
, we’ll use s
to ‘step’ into the method and then n
to go through the next subsequent lines until our program completes):
(rdb:1) s
app.rb:2: result = bar
(rdb:1) l
[-3, 6] in app.rb
1 def foo(msg)
=> 2 result = bar
3 msg
4 end
5
6 def bar
(rdb:1) s
app.rb:7: thing = 123
(rdb:1) l
[2, 11] in app.rb
2 result = bar
3 msg
4 end
5
6 def bar
=> 7 thing = 123
8 thing
9 end
10
11 require "debug"
(rdb:1) v l
thing => nil
(rdb:1) n
app.rb:8: thing
(rdb:1) v l
thing => 123
(rdb:1) n
app.rb:3: msg
(rdb:1) l
[-2, 7] in app.rb
1 def foo(msg)
2 result = bar
=> 3 msg
4 end
5
6 def bar
7 thing = 123
(rdb:1) result
123
(rdb:1) v l
msg => :hai
result => 123
(rdb:1) n
:hai