DEBUGGER__

This library provides debugging functionality to Ruby.

To add a debugger to your code, start by requiring debug in your program:

def say(word)
 require 'debug'
 puts word
end

This will cause Ruby to interrupt execution and show a prompt when the say method is run.

Once you're inside the prompt, you can start debugging your program.

(rdb:1) p word
"hello"

Getting help

You can get help at any time by pressing h.

(rdb:1) 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
 p expression evaluate expression and print its value
 h[elp] print this help
 <everything else> evaluate

Usage

The following is a list of common functionalities that the debugger provides.

Navigating through your code

In general, a debugger is used to find bugs in your program, which often means pausing execution and inspecting variables at some point in time.

Let's look at an example:

def my_method(foo)
 require 'debug'
 foo = get_foo if foo.nil?
 raise if foo.nil?
end

When you run this program, the debugger will kick in just before the foo assignment.

(rdb:1) p foo
nil

In this example, it'd be interesting to move to the next line and inspect the value of foo again. You can do that by pressing n:

(rdb:1) n # goes to next line
(rdb:1) p foo
nil

You now know that the original value of foo was nil, and that it still was nil after calling get_foo.

Other useful commands for navigating through your code are:

c

Runs the program until it either exists or encounters another breakpoint. You usually press c when you are finished debugging your program and want to resume its execution.

s

Steps into method definition. In the previous example, s would take you inside the method definition of get_foo.

r

Restart the program.

q

Quit the program.

Inspecting variables

You can use the debugger to easily inspect both local and global variables. We've seen how to inspect local variables before:

(rdb:1) p my_arg
42

You can also pretty print the result of variables or expressions:

(rdb:1) pp %w{a very long long array containing many words}
["a",
 "very",
 "long",
 ...
]

You can list all local variables with +v l+:

(rdb:1) v l
 foo => "hello"

Similarly, you can show all global variables with +v g+:

(rdb:1) v g
 all global variables

Finally, you can omit p if you simply want to evaluate a variable or expression

(rdb:1) 5**2
25

Going beyond basics

Ruby Debug provides more advanced functionalities like switching between threads, setting breakpoints and watch expressions, and more. The full list of commands is available at any time by pressing h.

Staying out of trouble

Make sure you remove every instance of +require 'debug'+ before shipping your code. Failing to do so may result in your program hanging unpredictably.

Debug is not available in safe mode.

Public Class Methods

break_points() click to toggle source

Returns the list of break points where execution will be stopped.

See DEBUGGER__ for more usage

 
 # File debug.rb, line 928
def break_points
 @break_points
end
 
context(thread=Thread.current) click to toggle source
 
 # File debug.rb, line 982
def context(thread=Thread.current)
 c = thread[:__debugger_data__]
 unless c
 thread[:__debugger_data__] = c = Context.new
 end
 c
end
 
debug_thread_info(input, binding) click to toggle source
 
 # File debug.rb, line 1061
def debug_thread_info(input, binding)
 case input
 when /^l(?:ist)?/
 make_thread_list
 thread_list_all
 when /^c(?:ur(?:rent)?)?$/
 make_thread_list
 thread_list(@thread_list[Thread.current])
 when /^(?:sw(?:itch)?\s+)?(\d+)/
 make_thread_list
 th = get_thread(1ドル.to_i)
 if th == Thread.current
 @stdout.print "It's the current thread.\n"
 else
 thread_list(@thread_list[th])
 context(th).stop_next
 th.run
 return :cont
 end
 when /^stop\s+(\d+)/
 make_thread_list
 th = get_thread(1ドル.to_i)
 if th == Thread.current
 @stdout.print "It's the current thread.\n"
 elsif th.stop?
 @stdout.print "Already stopped.\n"
 else
 thread_list(@thread_list[th])
 context(th).suspend
 end
 when /^resume\s+(\d+)/
 make_thread_list
 th = get_thread(1ドル.to_i)
 if th == Thread.current
 @stdout.print "It's the current thread.\n"
 elsif !th.stop?
 @stdout.print "Already running."
 else
 thread_list(@thread_list[th])
 th.run
 end
 end
end
 
display() click to toggle source

Returns the display expression list

See DEBUGGER__ for more usage

 
 # File debug.rb, line 921
def display
 @display
end
 
get_thread(num) click to toggle source
 
 # File debug.rb, line 994
def get_thread(num)
 th = @thread_list.key(num)
 unless th
 @stdout.print "No thread ##{num}\n"
 throw :debug_error
 end
 th
end
 
interrupt() click to toggle source
 
 # File debug.rb, line 990
def interrupt
 context(@last_thread).stop_next
end
 
make_thread_list() click to toggle source
 
 # File debug.rb, line 1048
def make_thread_list
 hash = {}
 for th in Thread::list
 if @thread_list.key? th
 hash[th] = @thread_list[th]
 else
 @max_thread += 1
 hash[th] = @max_thread
 end
 end
 @thread_list = hash
end
 
resume() click to toggle source
 
 # File debug.rb, line 966
def resume
 MUTEX.synchronize do
 make_thread_list
 @thread_list.each do |th,|
 next if th == Thread.current
 context(th).clear_suspend
 end
 waiting.each do |th|
 th.run
 end
 waiting.clear
 end
 # Schedule other threads to restart as soon as possible.
 Thread.pass
end
 
set_last_thread(th) click to toggle source
 
 # File debug.rb, line 950
def set_last_thread(th)
 @last_thread = th
end
 
set_trace( arg ) click to toggle source
 
 # File debug.rb, line 940
def set_trace( arg )
 MUTEX.synchronize do
 make_thread_list
 for th, in @thread_list
 context(th).set_trace arg
 end
 end
 arg
end
 
stdout() click to toggle source

Returns the IO used as stdout. Defaults to STDOUT

 
 # File debug.rb, line 909
def stdout
 @stdout
end
 
stdout=(s) click to toggle source

Sets the IO used as stdout. Defaults to STDOUT

 
 # File debug.rb, line 914
def stdout=(s)
 @stdout = s
end
 
suspend() click to toggle source
 
 # File debug.rb, line 954
def suspend
 MUTEX.synchronize do
 make_thread_list
 for th, in @thread_list
 next if th == Thread.current
 context(th).set_suspend
 end
 end
 # Schedule other threads to suspend as soon as possible.
 Thread.pass
end
 
thread_list(num) click to toggle source
 
 # File debug.rb, line 1003
def thread_list(num)
 th = get_thread(num)
 if th == Thread.current
 @stdout.print "+"
 else
 @stdout.print " "
 end
 @stdout.printf "%d ", num
 @stdout.print th.inspect, "\t"
 file = context(th).instance_eval{@file}
 if file
 @stdout.print file,":",context(th).instance_eval{@line}
 end
 @stdout.print "\n"
end
 
thread_list_all() click to toggle source

Prints all threads in @thread_list to @stdout. Returns a sorted array of values from the @thread_list hash.

While in the debugger you can list all of the threads with: DEBUGGER__.thread_list_all

(rdb:1) DEBUGGER__.thread_list_all
+1 #<Thread:0x007fb2320c03f0 run> debug_me.rb.rb:3
 2 #<Thread:0x007fb23218a538 debug_me.rb.rb:3 sleep>
 3 #<Thread:0x007fb23218b0f0 debug_me.rb.rb:3 sleep>
[1, 2, 3]

Your current thread is indicated by a +

Additionally you can list all threads with th l

(rdb:1) th l
 +1 #<Thread:0x007f99328c0410 run> debug_me.rb:3
 2 #<Thread:0x007f9932938230 debug_me.rb:3 sleep> debug_me.rb:3
 3 #<Thread:0x007f9932938e10 debug_me.rb:3 sleep> debug_me.rb:3

See DEBUGGER__ for more usage.

 
 # File debug.rb, line 1042
def thread_list_all
 for th in @thread_list.values.sort
 thread_list(th)
 end
end
 
waiting() click to toggle source

Returns the list of waiting threads.

When stepping through the traces of a function, thread gets suspended, to be resumed later.

 
 # File debug.rb, line 936
def waiting
 @waiting
end
 

AltStyle によって変換されたページ (->オリジナル) /