| [Top] | [Contents] | [Index] | [ ? ] |
This file describes ruby-debug, the Ruby Debugger, version 0.10.1
This is the 0.10.1 Edition, 20 April 2008
1. Summary of ruby-debug | Overview of Debugger with sample sessions | |
| 2. Getting in and out | ||
3. ruby-debug Command Reference | rdebug command reference | |
| 4. Post-Mortem Debugging | Debugging on an uncaught exception | |
| 5. The Debugger Module and Class | ruby-debug's Debugger module and class | |
Appendix | ||
|---|---|---|
| A. Building and Installing from rubyforge's Subversion Repository | ||
Indexes (nodes containing large menus) | ||
| Class, Module Method Index | An item for Class, Module, and Methods. | |
| Command Index | An item for each command name. | |
| General Index | An item for each concept. | |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ruby-debug The purpose of a debugger such as ruby-debug is to allow you to see what is going on "inside" a Ruby program while it executes.
rdebug can do four main kinds of things (plus other things in support of
these) to help you catch bugs in the act:
Although you can use rdebug to invoke your Ruby programs via
a debugger at the outset, there are other ways to use and enter the
debugger.
1.1 The First Sample rdebug Session (list, display, print, and quit) | A Simple Sample rdebug session
| |
1.2 Sample Session 2: Delving Deeper (where, frame, restart, autoeval, break, ps) | Second Session Delving a little deeper rdebug session
| |
1.3 Using the debugger in unit testing (ruby-debug/debugger, Debugger.start) | Using the debugger in unit testing | |
| 1.4 How debugging Ruby may be different than debugging other Languages | How debugging Ruby may be different... |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
rdebug Session (list, display, print, and quit) You can use this manual at your leisure to read all about ruby-debug.
However, a handful of commands are enough to get started using the
debugger. The following sections illustrates these commands.
Below is Ruby code to compute a triangle number of a given length.(1)
$ rdebug triangle.rb triangle.rb:4 def hanoi(n,a,b,c) (rdb:1) list [-1, 8] in ./triangle.rb 1 #!/usr/bin/env ruby 2 # Compute the n'th triangle number - the hard way 3 # triangle(n) == (n * (n+1)) / 2 => 4 def triangle(n) 5 tri = 0 6 0.upto(n) do |i| 7 tri += i 8 end (rdb:1) l [9, 18] in ./triangle.rb 9 return tri 10 end 11 12 puts triangle(3) (rdb:1) list 1,100 [1, 100] in ./triangle.rb 1 #!/usr/bin/env ruby 2 # Compute the n'th triangle number - the hard way 3 # triangle(n) == (n * (n+1)) / 2 => 4 def triangle(n) 5 tri = 0 6 0.upto(n) do |i| 7 tri += i 8 end 9 return tri 10 end 11 12 puts triangle(3) (rdb:1) |
There are lots of command options, but we don't need them for now. See Options you can pass to rdebug for a full list of command options.
Position information consists of a filename and line number,
e.g. triangle.rb:4. We are currently stopped before the first
executable line of the program; this is line 4 of
triangle.rb. If you are used to less dynamic languages and have
used debuggers for more statically compiled languages like C, C++, or
Java, it may seem odd to be stopped before a function definition. But
in Ruby line 4 is executed, the name triangle (probably) does
not exist so issuing a method call of triangle will raise a
"method not found" error.
ruby-debug's prompt is (rdb:n). The n is the thread
number. Here it is 1 which is usually the case for the main thread. If
the program has died and you are in post-mortem debugging, there is no
thread number. In this situation, the string post-mortem is
used in place of a thread number. If the program has terminated
normally, the string this position will be ctrl. The commands
which are available change depending on the program state.
The first command, list (see section Examining Program Source Files (`list')), prints 10 lines
centered around the current line; the current line here is line 4 and
is marked by =>, so the range the debugger would like to show
is -1..8. However since there aren't 5 lines before the current line,
those additional lines--"lines" -1 and 0--are dropped and we print
the remaining 8 lines. The list command can be abbreviated
with l which is what we use next. Notice that when we use this
a second time, we continue listing from the place we last left
off. The desired range of lines this time is lines 9 to 18; but since
the program ends as line 12, only the remaining 4 lines are shown.
If you want to set how many lines to print by default rather than use
the initial number of lines, 10, use the set listsize command
(see section Set/Show lines in a List command). To see the entire program in one shot, we gave an
explicit starting and ending line number.
If you use a front-end to the debugger such as the Emacs interface,
you probably won't use list all that much.
Now let us step through the program.
(rdb:1) step triangle.rb:12 puts triangle(3) (rdb:1) <RET> triangle.rb:5 tri = 0 (rdb:1) p tri nil (rdb:1) step triangle.rb:6 0.upto(n) do |i| (rdb:1) p tri 0 |
The first step command (see section Step (`step')) runs the script one
executable unit. The second command we entered was just hitting the
return key; rdebug remembers the last command you entered was
step, so it runs that last command again.
One way to print the values of variables uses p. (Of course,
there are of course lots of other ways too.). When we look at the
value of tri the first time, we see it is nil. Again we
are stopped before the assignment on line 5, and this variable
hasn't been set previously. However after issuing another "step"
command we see that the value is 0 as expected.
If we want to see the value of tri every time we stop to see
how this is going to change we can give a display expression
(see section Executing expressions on stop (`display', `undisplay')).
(rdb:1) display tri 1: tri = 0 |
Now let us run the program until we return from the function. However we'll want to see which lines get run.
(rdb:1) display i 2: i = (rdb:1) set linetrace on line tracing is on. (rdb:1) finish Tracing(1):triangle.rb:7 tri += i 1: tri = 0 2: i = 0 Tracing(1):triangle.rb:7 tri += i 1: tri = 0 2: i = 1 Tracing(1):triangle.rb:7 tri += i 1: tri = 1 2: i = 2 Tracing(1):triangle.rb:7 tri += i 1: tri = 3 2: i = 3 Tracing(1):triangle.rb:9 return tri 1: tri = 6 2: i = (rdb:1) quit Really quit? (y/n) y |
So far, so good. A you can see from the above to get out of the
debugger, one can issue a quit command.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
where, frame, restart, autoeval, break, ps) In this section we'll introduce breakpoints, the call stack and restarting. So far we've been doing pretty good in that we've not encountered a bug to fix. Let's try another simple example. Okay here's the program.
Below we will debug a simple Ruby program to solve the classic Towers of Hanoi puzzle. It is augmented by the bane of programming: some command-parameter processing with error checking.
$ rdebug hanoi.rb hanoi.rb:3 def hanoi(n,a,b,c) (rdb:1) list 1,100 [1, 100] in ./hanoi.rb 1 #!/usr/bin/ruby 2 => 3 def hanoi(n,a,b,c) 4 if n-1 > 0 5 hanoi(n-1, a, c, b) 6 end 7 puts "Move disk %s to %s" % [a, b] 8 if n-1 > 0 9 hanoi(n-1, c, b, a) 10 end 11 end 12 13 i_args=ARGV.length 14 if i_args > 1 15 puts "*** Need number of disks or no parameter" 16 exit 1 17 end 18 19 n=3 20 21 if i_args > 0 22 begin 23 n = ARGV[0].to_i 24 rescue ValueError, msg: 25 print "** Expecting an integer, got: %s" % ARGV[0].to_s 26 exit 2 27 end 28 end 29 30 if n < 1 or n > 100 31 puts "*** number of disks should be between 1 and 100" 32 exit 2 33 end 34 35 hanoi(n, :a, :b, :c) (rdb:1) |
Recall in the first section I said that before the def is run
the method it names is undefined. Let's check that out. First let's
see what private methods we can call before running def hanoi
(rdb:1) set autoeval on autoeval is on. (rdb:1) private_methods ["select", "URI", "local_variables", "lambda", "chomp", ... |
The set autoeval (see section Set/Show auto-eval) command causes any commands
that are not normally understood to be debugger commands to get
evaluated as though they were Ruby commands. I use this a lot, so I
set this by putting it the command file .rdebugrc,
see section Command files, that gets read when ruby-debug starts.
As showing the list output of private_methods, I find this kind
of list unwieldy. What you are supposed to notice here is that
method hanoi is not in this list. When you ask
ruby-debug for a list of method names via method
instance, it doesn't show output in this way; ruby-debug can
sort and put into columns lists like this using the print command, ps.
(rdb:1) ps private_methods Array exit! puts warn Float fail raise y Integer fork rand Rational format readline String gem_original_require readlines URI getc remove_instance_variable ` gets scan abort global_variables select active_gem_with_options gsub set_trace_func at_exit gsub! singleton_method_added autoload initialize singleton_method_removed autoload? initialize_copy singleton_method_undefined binding iterator? sleep block_given? lambda split callcc load sprintf caller local_variables srand catch location_of_caller sub chomp loop sub! chomp! method_missing syscall chop open system chop! p test dbg_print pp throw dbg_puts print timeout eval printf trace_var exec proc trap exit putc untrace_var |
Now let's see what happens after stepping
(rdb:1) private.methods.member?("hanoi")
false
(rdb:1) step
hanoi.rb:13
i_args=ARGV.length
(rdb:1) private_methods.member?("hanoi")
true
(rdb:1)
|
Okay, now where were we?
(rdb:1) list [8, 17] in ./hanoi.rb 8 if n-1 > 0 9 hanoi(n-1, c, b, a) 10 end 11 end 12 => 13 i_args=ARGV.length 14 if i_args > 1 15 puts "*** Need number of disks or no parameter" 16 exit 1 17 end (rdb:1) ARGV [] |
Ooops. We forgot to specify any parameters to this program. Let's try
again. We can use the restart command here.
(rdb:1) restart 3
Re exec'ing:
/usr/bin/rdebug hanoi.rb 3
hanoi.rb:3
def hanoi(n,a,b,c)
(rdb:1) break 4
Breakpoint 1 file hanoi.rb, line 4
(rdb:1) continue
Breakpoint 1 at hanoi.rb:4
./hanoi.rb:4 if n-1 > 0
(rdb:1) display n
1: n = 3
(rdb:1) display a
2: a = a
(rdb:1) undisplay 2
(rdb:1) display a.inspect
3: a.inspect = :a
(rdb:1) display b.inspect
4: b.inspect = :b
(rdb:1) continue
Breakpoint 1 at hanoi.rb:4
./hanoi.rb:4
if n-1 > 0
1: n = 2
3: a.inspect = :a
4: b.inspect = :c
(rdb:1) c
Breakpoint 1 at hanoi.rb:4
./hanoi.rb:4
if n-1 > 0
1: n = 1
3: a.inspect = :a
4: b.inspect = :b
(rdb:1) where
--> #0 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:4
#1 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5
#2 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5
#3 at line hanoi.rb:35
(rdb:1)
|
In the above we added a new command, break
(see section Breakpoints (`break', `catch', `delete')) which indicates to go into the debugger just
before that line of code is run. And continue resumes
execution. Notice the difference between display a and
display a.inspect. An implied string conversion is performed on
the expression after it is evaluated. To remove a display expression
we used undisplay is used. If we give a display number, just
that display expression is removed.
Above we also used a new command where (see section Backtraces (`where') to
show the call stack. In the above situation, starting from the bottom
line we see we called the hanoi from line 35 of the file
hanoi.rb and the hanoi method called itself two more times at
line 5.
In the call stack we show the file line position in the same format when we stop at a line. Also we see the names of the parameters and the types that those parameters currently have. It's possible that when the program was called the parameter had a different type, since the types of variables can change dynamically. You alter the style of what to show in the trace (see section Set/Show call style).
Let's explore a little more. Now were were we?
(rdb:1) list 1 #!/usr/bin/ruby 2 3 def hanoi(n,a,b,c) => 4 if n-1 > 0 5 hanoi(n-1, a, c, b) 6 end 7 puts "Move disk %s to %s" % [a, b] 8 if n-1 > 0 (rdb:1) undisplay Clear all expressions? (y/n) y (rdb:1) i_args NameError Exception: undefined local variable or method `i_args' for main:Object (rdb:1) frame -1 #3 at line hanoi.rb:35 (rdb:1) i_args 1 (rdb:1) p n 3 (rdb:1) down 2 #2 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5 (rdb:1) p n 2 |
Notice in the above to get the value of variable n, I have to
use a print command like p n; If I entered just n, that
would be taken to mean the debugger command "next". In the current
scope, variable i_args is not defined. However I can change to
the top-most frame by using the frame command. Just as with
arrays, -1 means the last one. Alternatively using frame number 3
would have been the same thing; so would issuing up 3.
Note that in the outside frame 3, the value of i_args can be
shown. Also note that the value of variable n is different.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ruby-debug/debugger, Debugger.start) In the previous sessions we've been calling the debugger right at the outset. I confess that this mode of operation is usually not how I use the debugger.
There are a number of situations where calling the debugger at the outset is impractical for a couple of reasons.
In this section we'll delve show how to enter the code in the middle of your program, while delving more into the debugger operation.
In this section we will also use unit testing. Using unit tests will greatly reduce the amount of debugging needed while at the same time increase the quality of your program.
What we'll do is take the triangle code from the first session
and write a unit test for that. In a sense we did write a mini-test
for the program which was basically the last line where we printed the
value of triangle(3). This test however wasn't automated: the
implication is that someone would look at the output and verify that
what was printed is what was expected.
And before we can turn that into something that can be
required, we probably want to remove that output. However I
like to keep in that line so that when I look at the file, I have an
example of how to run it. Therefore we will conditionally run this
line if that file is invoked directly, but skip it if it is
not.(2)
if __FILE__ == $0
puts triangle(3)
end
|
Let's call this file tri2.rb.
Okay, we're now ready to write our unit test. We'll use
"test/unit" which comes with the standard Ruby distribution.
Here's the test code:
#!/usr/bin/env ruby
require 'test/unit'
require 'tri2.rb'
class TestTri < Test::Unit::TestCase
def test_basic
solutions = []
0.upto(5) do |i|
solutions << triangle(i)
end
assert_equal([0, 1, 3, 6, 10, 15], solutions,
'Testing the first 5 triangle numbers')
end
end
|
If you run it will work. However if you run rdebug initially,
you will not get into the test, because test/unit wants to be
the main program. So here is a situation where one may need to modify
the program to add an explicit call to the debugger.(3)
One way to do this is to add the following before the place you want to stop:
require 'rubygems' require 'ruby-debug/debugger' |
The line require "rubygems" is needed if ruby-debug is
installed as a Ruby gem.
Let's add this code just after entering test_basic:
...
def test_basic
require "rubygems"
require "ruby-debug/debugger"
solutions = []
...
|
Now we run the program..
$ ruby test-tri.rb Loaded suite test-tri Started test-tri.rb:9 solutions = [] (rdb:1) |
and we see that we are stopped at line 9 just before the
initialization of the list solutions.
Now let's see where we are...
(rdb:1) where --> #0 TestTri.test_basic at line /home/rocky/ruby/test-tri.rb:9 (rdb:1) |
Something seems wrong here; TestTri.test_basic indicates that
we are in class TestTri in method test_basic. However we
don't see the call to this like we did in the last example when we
used the where command. This is because the debugger really
didn't spring into existence until after we already entered that
method, and Ruby doesn't keep call stack information around in a
way that will give the information we show when running where.
If we want call stack information, we have to turn call-stack tracking
on beforehand. This is done by adding Debugger.start.
Here's what our test program looks like so after we modify it to start tracking calls from the outset
#!/usr/bin/env ruby
require 'test/unit'
require 'tri2.rb'
require 'rubygems'
Debugger.start
class TestTri < Test::Unit::TestCase
def test_basic
debugger
solutions = []
0.upto(5) do |i|
solutions << triangle(i)
end
assert_equal([0, 1, 3, 6, 10, 15], solutions,
"Testing the first 5 triangle numbers")
end
end
|
Now when we run this:
$ ruby test-tri2.rb
Loaded suite test-tri2
Started
test-tri2.rb:11
solutions = []
(rdb:1) where
--> #0 TestTri.test_basic at line test-tri2.rb:11
#1 Kernel.__send__(result#Test::Unit::TestResult)
at line /usr/lib/ruby/1.8/test/unit/testcase.rb:70
#2 Test::Unit::TestCase.run(result#Test::Unit::TestResult)
at line /usr/lib/ruby/1.8/test/unit/testcase.rb:70
...
#11 Test::Unit::AutoRunner.run
at line /usr/lib/ruby/1.8/test/unit/autorunner.rb:200
#12 Test::Unit::AutoRunner.run(force_standalone#FalseClass, ...
at line /usr/lib/ruby/1.8/test/unit/autorunner.rb:13
#13 at line /usr/lib/ruby/1.8/test/unit.rb:285
(rdb:1)
|
Much better. But again let me emphasize that the parameter types are
those of the corresponding variables that currently exist, and
this might have changed since the time when the call was made. Even so
and even though we only have types listed, it's a pretty good
bet that when Test::Unit was first called, shown above as frame
12, that the values of its two parameters were false and
nil.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
If you are used to debugging in other languages like C, C++, Perl, Java or even Bash(4), there may be a number of things that seem or feel a little bit different and may confuse you. A number of these things aren't oddities of the debugger per see, so much as a difference in how Ruby works compared to those other languages. Because Ruby works a little differently from those other languages, writing a debugger has to also be a little different as well if it is to be useful.
In this respect, using the debugger may help you understand Ruby better.
We've already seen two examples of such differences. One difference is
the fact that we stop on method definitions or def's and that's
because these are in fact executable statements. In other compiled
languages this would not happen because that's already been done when
you compile the program (or in Perl when it scans in the program). The
other difference we saw was in our inability to show call stack parameter
types without having made arrangements for the debugger to track
this. In other languages call stack information is usually available
without asking assistance of the debugger.(5)
In this section we'll consider some other things that might throw off new users to Ruby who are familiar with other languages and debugging in them.
| 1.4.1 Stack Shows Scope Nesting | ||
| 1.4.2 More Frequent Evaluations per Line | ||
| 1.4.3 Bouncing Around in Blocks (e.g. Iterators) | ||
| 1.4.4 No Parameter Values in a Call Stack | ||
| 1.4.5 Lines You Can Stop At |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In a backtrace, you will find more stack frames than you might in say C.
Consider another way to write the triangle program of see section The First Sample rdebug Session (list, display, print, and quit).
1 #!/usr/bin/env ruby 2 def triangle(n) 3 (0..n).inject do |sum, i| 4 sum +=i 5 end 6 end 7 puts triangle(3) |
Let's stop inside the inject block:
$ rdebug tri3.rb
(rdb:1) c 4
tri3.rb:4
sum +=i
(rdb:1) where
--> #0 Range.triangle at line tri3.rb:4
#1 Enumerable.inject at line tri3.rb:3
#2 Object.triangle(n#Fixnum) at line tri3.rb:3
#3 at line tri3.rb:7
(rdb:1)
|
Because a new scope was entered, it appears as a stack frame. Probably "scope" frame would be a more appropriate name.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Consider this simple program to compute the Greatest Common Divisor of two numbers:
1 #!/usr/bin/env ruby
2 # GCD. We assume positive numbers
3
4 def gcd(a, b)
5 # Make: a <= b
6 if a > b
7 a, b = [b, a]
8 end
9
10 return nil if a <= 0
11
12 if a == 1 or b-a == 0
13 return a
14 end
15 return gcd(b-a, a)
16 end
17
18 a, b = ARGV[0..1].map {|arg| arg.to_i}
19 puts "The GCD of %d and %d is %d" % [a, b, gcd(a, b)]
|
Now let's try tracing a portion of the program to see what we get.
$ rdebug gcd.rb 3 5
gcd.rb:4
def gcd(a, b)
(rdb:1) step
gcd.rb:18
a, b = ARGV[0..1].map {|arg| arg.to_i}
(rdb:1) step
gcd.rb:18
a, b = ARGV[0..1].map {|arg| arg.to_i}
(rdb:1) step
gcd.rb:18
a, b = ARGV[0..1].map {|arg| arg.to_i}
(rdb:1) step
(rdb:1) break Object.gcd
Breakpoint 1 at Object::gcd
(rdb:1) continue
Breakpoint 1 at Object:gcd
gcd.rb:4
def gcd(a, b)
(rdb:1) set linetrace on
line tracing is on.
(rdb:1) continue
Tracing(1):gcd.rb:6 if a > b
Tracing(1):gcd.rb:6 if a > b
Tracing(1):gcd.rb:10 return nil if a <= 0
Tracing(1):gcd.rb:10 return nil if a <= 0
Tracing(1):gcd.rb:12 if a == 1 or b-a == 0
Tracing(1):gcd.rb:12 if a == 1 or b-a == 0
Tracing(1):gcd.rb:15 return gcd(b-a, a)
Breakpoint 1 at Object:gcd
gcd.rb:4
def gcd(a, b)
(rdb:1)
|
The thing to note here is that we see lots of lines duplicated. For example, the first line:
Tracing(1):gcd.rb:18 a, b = ARGV[0..1].map {|arg| arg.to_i}
|
appears three times. If we were to break this line into the equivalent multi-line expression:
a, b = ARGV[0..1].map do |arg| arg.to_i end |
we would find one stop at the first line before running map and
two listings of arg.to_i, once for each value of arg which here
is 0 and then 1. Perhaps this is is not surprising because we have a
loop here which gets run in this situation 3 times. A similar command
next, can also be used to skip over loops and method
calls.
But what about all the duplicated if statements in gcd?
Each one is listed twice whether or not we put the if at the
beginning or the end. You will find this to be the case for any
conditional statement such as until or while.
Each statement appears twice because we stop once before the expression is evaluated and once after the expression is evaluated but before the if statement takes hold. There is a bug in Ruby up to version 1.8.6 in that we stop a second time before the evaluation, so examining values that may have changed during the expression evaluation doesn't work in these versions.
If you are issuing a step command one at a time, the repetitive
nature can be little cumbersome if not annoying. So ruby-debug offers
a variant called step+ which forces a new line on every
step. Let's try that.
(rdb:1) R
Re exec'ing:
/usr/bin/rdebug gcd.rb 3 5
gcd.rb:4
def gcd(a, b)
(rdb:1) step+
gcd.rb:18
a, b = ARGV[0..1].map {|arg| arg.to_i}
(rdb:1) step+
gcd.rb:19
puts "The GCD of %d and %d is %d" % [a, b, gcd(a, b)]
(rdb:1) break Object.gcd
Breakpoint 1 at Object:gcd
(rdb:1) c
Breakpoint 1 at Object:gcd
gcd.rb:4
def gcd(a, b)
(rdb:1) set linetrace+
line tracing style is different consecutive lines.
(rdb:1) set linetrace on
line tracing is on.
(rdb:1) c
Tracing(1):gcd.rb:6 if a > b
Tracing(1):gcd.rb:10 return nil if a <= 0
Tracing(1):gcd.rb:12 if a == 1 or b-a == 0
Tracing(1):gcd.rb:15 return gcd(b-a, a)
Breakpoint 1 at Object:gcd
gcd.rb:4
def gcd(a, b)
|
If you want step+ to be the default behavior when stepping,
issue the command set forcestep on, (see section Set/Show Forces Different Line Step/Next). I
generally put this in my start-up file .rdebugrc.
Similar to the difference between step+ and step is
set linetrace+. This removes duplicate consecutive line tracing.
One last thing to note above is the use of a method name to set a
breakpoint position, rather than a file and line number. Because
method gcd is in the outermost scope, we use Object as the
class name.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When debugging languages with coroutines like Python and Ruby, a
method call may not necessarily go to the first statement after the
method header. It's possible the call will continue after a
yield statement from a prior call.
1 #!/usr/bin/env ruby 2 # Enumerator for primes 3 class SievePrime 4 @@odd_primes = [] 5 def self.next_prime(&block) 6 candidate = 2 7 yield candidate 8 not_prime = false 9 candidate += 1 10 while true do 11 @@odd_primes.each do |p| 12 not_prime = (0 == (candidate % p)) 13 break if not_prime 14 end 15 unless not_prime 16 @@odd_primes << candidate 17 yield candidate 18 end 19 candidate += 2 20 end 21 end 22 end 23 SievePrime.next_prime do |prime| 24 puts prime 25 break if prime > 10 26 end |
$ rdebug primes.rb primes.rb:3 class SievePrime (rdb:1) set linetrace on line tracing is on. (rdb:1) step 10 Tracing(1):primes.rb:4 @odd_primes = [] Tracing(1):primes.rb:5 def self.next_prime(&block) Tracing(1):primes.rb:23 SievePrime.next_prime do |prime| Tracing(1):primes.rb:6 candidate = 2 Tracing(1):primes.rb:7 yield candidate Tracing(1):primes.rb:24 puts prime 2 Tracing(1):primes.rb:25 break if prime > 10 Tracing(1):primes.rb:25 break if prime > 10 Tracing(1):primes.rb:8 not_prime = false Tracing(1):primes.rb:9 candidate += 1 primes.rb:9 candidate += 1 (rdb:1) |
The loop between lines 23-26 gets interleaved between those of
Sieve::next_prime, lines 6-19 above.
A similar kind of thing can occur in debugging programs with many threads.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In traditional debuggers in a call stack you can generally see the names of the parameters and the values that were passed in.
Ruby is a very dynamic language and it tries to be efficient within the confines of the language definition. Values generally aren't taken out of a variable or expression and pushed onto a stack. Instead a new scope created and the parameters are given initial values. Parameter passing is by reference, not by value as it is say Algol, C, or Perl. During the execution of a method, parameter values can change--and often do. In fact even the class of the object can change.
So at present, the name of the parameter shown. The call-style setting see section Set/Show call style can be used to set whether the name is shown or the name and the current class of the object.
It has been contemplated that a style might be added which saves on call shorter "scalar" types of values and the class name.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
As with the duplicate stops per control (e.g. if statement),
until tools like debuggers get more traction among core ruby
developers there are going to be weirdness. Here we describe the
stopping locations which effects the breakpoint line numbers you can
stop at.
Consider the following little Ruby program.
'Yes it does' =~ / (Yes) \s+ it \s+ does /ix puts $1 |
The stopping points that Ruby records are the last two lines, lines 5
and 6. If you run ruby -rtracer on this file you'll see that
this is so:
$ ruby -rtracer lines.rb #0:lines.rb:5::-: /ix #0:lines.rb:6::-: puts $1 #0:lines.rb:6:Kernel:>: puts $1 #0:lines.rb:6:IO:>: puts $1 Yes#0:lines.rb:6:IO:<: puts $1 #0:lines.rb:6:IO:>: puts $1 #0:lines.rb:6:IO:<: puts $1 #0:lines.rb:6:Kernel:<: puts $1 |
Inside ruby-debug you an get a list of stoppable lines for a
file using the info file command with the attribute
breakpoints.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
| 2.1 Starting the debugger | How to enter the debugger | |
| 2.2 Command files | ||
| 2.3 Quitting the debugger | How to leave the debugger (quit, kill) | |
| 2.4 Calling the debugger from inside your Ruby program | Calling the debugger from inside your program |
It is also possible to enter the debugger when you have an uncaught exception. See See also Post-Mortem Debugging.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Although one can enter ruby-debug via Emacs (described in a later section) and possibly others interfaces, probably the most familiar thing to do is invoke the debugger from a command line.
A wrapper shell script called rdebug basically require's
the gem package ruby-debug and then loads rdebug.
rdebug [rdebug-options] [--] ruby-script ruby-script-arguments... |
If you don't need to pass dash options to your program which might get
confused with the debugger options, then you don't need to add the
--.
To get a brief list of options and descriptions, use the --help
option.
$ rdebug --help
rdebug 0.10.1
Usage: rdebug [options] <script.rb> -- <script.rb parameters>
Options:
-A, --annotate LEVEL Set annotation level
-c, --client Connect to remote debugger
--cport PORT Port used for control commands
-d, --debug Set $DEBUG=true
--emacs Activates full Emacs support
--emacs-basic Activates basic Emacs mode
-h, --host HOST Host name used for remote debugging
-I, --include PATH Add PATH to $LOAD_PATH
--keep-frame-binding Keep frame bindings
-m, --post-mortem Activate post-mortem mode
--no-control Do not automatically start control thread
--no-quit Do not quit when script finishes
--no-rewrite-program Do not set $0 to the program being debugged
--no-stop Do not stop when script is loaded
-p, --port PORT Port used for remote debugging
-r, --require SCRIPT Require the library, before executing your script
--script FILE Name of the script file to run
-s, --server Listen for remote connections
-w, --wait Wait for a client connection, implies -s option
-x, --trace Turn on line tracing
Common options:
--verbose Turn on verbose mode
--help Show this message
--version Print the version
-v Print version number, then turn on verbose mode
|
Options for the rdebug are shown in the following list.
| 2.1.1 Options you can pass to rdebug | ||
| 2.1.2 How to Set Default Command-Line Options |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can run ruby-debug in various alternative modes--for example, as a program that interacts directly with the program in the same process on the same computer or via a socket to another process possibly on a different computer.
Many options appear as a long option name, such as --help, and
a short one letter option name, such as -h. A double dash
(-- is used to separate options which go to rdebug from
options that are intended to go to your Ruby script. Options (if any)
to rdebug should come first. If there is no possibility of the
Ruby script to be debugged getting confused with rdebug's
option the double dash can be omitted.
--helpThis option causes rdebug to print some basic help and exit.
-v | --versionThis option causes rdebug to print its version number and exit.
-A | --annotate levelSet gdb-style annotation level, a number. Additional information is output automatically when program state is changed. This can be used by front-ends such as GNU Emacs to post this updated information without having to poll for it.
-c | --clientConnect to remote debugger. The remote debugger should have been set
up previously our you will get a connection error and rdebug
will terminate.
--cport portPort used for control commands.
--debugSet $DEBUG to true. This option is compatible with
Ruby's.
--emacsActivates GNU Emacs mode. Debugger output is tagged in such a way to allow GNU Emacs to track where you are in the code.
--emacs-basicActivates full GNU Emacs mode.
This is the equivalent of setting the options --emacs-basic,
annotate=3, --no-stop, -no-control and
--post-mortem.
-h | --host host-addressConnect host address for remote debugging.
-I --include PATHAdd PATH to $LOAD_PATH
--keep-frame-bindingBindings are used to set the proper environment in evaluating expression inside the debugger. Under normal circumstances, I don't believe most people will ever need this option.
By default, the debugger doesn't create binding object for each frame when the frame is created, i.e. when a call is performed. Creating a binding is an expensive operation and has been a major source of performance problems.
Instead, the debugger creates a binding when there is a need to evaluate expressions. The artificial binding that is created might be different from the real one. In particular, in performing constant and module name resolution.
However it's still possible to restore the old, slower behavior by
using this option or by setting Debugger.keep_frame_binding =
true. There are two possibilities for which you might want to use
this option.
First, if you think there's a bug in the evaluation of variables, you might want to set this to see if this corrects things.
Second, since the internal structures that are used here FRAME
and SCOPE are not part of the Ruby specification, it is
possible they can change with newer releases; so here this option this
may offer a remedy. (But you'll probably also have to hack the C code
since it's likely under this scenario that ruby-debug will no longer
compile.) In fact, in Ruby 1.9 these structures have changed and that
is partly why this debugger doesn't work on Ruby 1.9.
-m | --post-mortemIf your program raises an exception that isn't caught you can enter
the debugger for inspection of what went wrong. You may also want to
use this option in conjunction with --no-stop. See also
Post-Mortem Debugging.
--no-controlDo not automatically start control thread.
--no-quitRestart the debugger when your program terminates normally.
--no-rewrite-programNormally rdebug will reset the program name $0 from its
name to the debugged program, and set the its name in variable
$RDEBUG_0. In the unlikely even you don't want this use this option.
--no-stopNormally the rdebug stops before executing the first
statement. If instead you want it to start running initially and will
perhaps break it later in the running, use this options.
-p | --port portPort used for remote debugging.
-r | --require libraryRequire the library, before executing your script. However if the
library happened to be debug, we'll just ignore the require
(since we're already a debugger). This option is compatible with Ruby's.
--script fileRequire the library, before executing your script. However if the
library hap-pend to be debug, we'll just ignore the require
(since we're already a debugger). This option is compatible with Ruby's.
-s | --serverDebug the program but listen for remote connections on the default
port or port set up via the --port option. See also --wait.
-w | --waitDebug the program but stop waiting for a client connection first. This
option automatically sets --server option.
-x | --traceTurn on line tracing. Running:
rdebug --trace rubyscript.rb |
is much line running:
ruby -rtracer rubyscript.rb |
If all you want to do however is get a linetrace, tracer, not
rdebug, may be faster:
$ time ruby -rtracer gcd.rb 34 21 > /dev/null real 0m0.266s user 0m0.008s sys 0m0.000s $ time rdebug --trace gcd.rb 34 21 > /dev/null real 0m0.875s user 0m0.448s sys 0m0.056s $ |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ruby-debug has many command-line options; it seems that some people want
to set them differently from the our defaults. For example, some
people may want --no-quit --no-control to be the default
behavior. One could write a wrapper script or set a shell alias to
handle this. ruby-debug has another way to do this as well. Before
processing command options if the file $HOME/.rdboptrc is found
it is loaded. If you want to set the defaults in some other way, you
can put Ruby code here and set variable options which is an
OpenStruct. For example here's how you'd set -no-quit and
change the default control port to 5000.
# This file contains how you want the default options to ruby-debug # to be set. Any Ruby code can be put here. # # debugger # Uncomment if you want to debug rdebug! options.control = false options.port = 5000 puts "rocky's rdboptrc run" |
Here are the default values in options
#<OpenStruct server=false, client=false, frame_bind=false, cport=8990, tracing=false, nx=false, post_mortem=false, port=8989, verbose_long=false, annotate=nil, control=true, restart_script=nil, quit=true, no_rewrite_program=false, stop=true, script=nil, host=nil, wait=false> |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A command file for ruby-debug is a file of lines that are ruby-debug commands. Comments (lines starting with #) may also be included. An empty line in a command file does nothing; it does not mean to repeat the last command, as it would from the terminal.
When you start ruby-debug, it automatically executes commands from its init files, normally called `.rdebugrc'.
On some configurations of ruby-debug, the init file may be known by a different name. In particular on MS-Windows (but not cygwin) `rdebug.ini' is used.
During startup, ruby-debug does the following:
HOME or HOMEPATH environment variable.
Thus, you can have more than one init file, one generic in your home directory, and another, specific to the program you are debugging, in the directory where you invoke ruby-debug.
You can also request the execution of a command file with the
source command, see section Running Debugger Commands (`source').
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An interrupt (often C-c) does not exit from ruby-debug, but
rather terminates the action of any ruby-debug
progress and returns to ruby-debug command level. Inside a debugger
command interpreter, use quit command (see section Quitting the debugger).
There way to terminate the debugger is to use the kill
command. This does more forceful kill -9. It can be used in
cases where quit doesn't work.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Running a program from the debugger adds a bit of overhead and slows down your program a little.
Furthermore, by necessity, debuggers change the operation of the program they are debugging. And this can lead to unexpected and unwanted differences. It has happened so often that the term "Heisenbugs" (see http://en.wikipedia.org/wiki/Heisenbug) was coined to describe the situation where the addition of the use of a debugger (among other possibilities) changes behavior of the program so that the bug doesn't manifest itself anymore.
There is another way to get into the debugger which adds no overhead or slowdown until you reach the point at which you want to start debugging. However here you must change the script and make an explicit call to the debugger. Because the debugger isn't involved before the first call, there is no overhead and the script will run at the same speed as if there were no debugger.
There are three parts to calling the debugger from inside the script, "requiring" the debugger code, telling the debugger to start tracking things and then making the call calling the debugger to stop.
To get the debugger class accessible from your Ruby program:
require 'rubygems' require 'ruby-debug' |
(It is very likely that you've already require'd rubygems. If so, you don't have to do that again.) These commands need to be done only once.
After require 'ruby-debug', it's possible to set some of the
debugger variables influence preferences. For example if you want to
have rdebug
variable Debugger.settings[:autolist]. see section Debugger.settings has a
list of variable settings and the default values. Debugger settings
can also be set in .rdebugrc as debugger
commands. see section Command files
To tell the debugger to start tracking things:
Debugger.start |
There is also a Debugger.stop to turn off debugger tracking. If
speed is crucial, you may want to start and stop this around certain
sections of code.
And finally to enter the debugger:
debugger |
As indicated above, when debugger is run a .rdebugrc
profile is read if that file exists.
You may want to do enter the debugger at several points in the program
where there is a problem you want to investigate. And since
debugger is just a method call it's possible enclose it in a
conditional expression, for example:
debugger if foo='bar' and iter_count = 20 |
Although each step does a very specific thing which offers great flexibility, in order to make getting into the debugger easier the three steps have been rolled into one command:
require "ruby-debug/debugger" |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ruby-debug Command Reference | 3.1 Command Interfaces | The kinds of interface used to interact with ruby-debug | |
| 3.2 Command Syntax | How to give commands to the ruby-debug | |
| 3.3 Command Output | How rdebug presents its output | |
| 3.4 Getting help (`help') | How to ask for help (help) | |
| 3.5 Controlling the debugger (`quit', `restart', `interrupt', `source') | Controlling the debugger (quit, restart, interrupt) | |
| 3.6 Executing expressions on stop (`display', `undisplay') | Executing expressions on stop (display, undisplay) | |
| 3.7 Evaluating and Printing Expressions (`p', `pp', `putl', `ps', `irb') | Evaluating and Printing Expressions (p, pp, ps, pp, irb) | |
| 3.8 Printing Variables (`var', `method') | Printing Variables (var) | |
| 3.9 Examining Program Source Files (`list') | Examining Program Source Files (list) | |
| 3.10 Editing Source files (`edit') | Editing source files (edit) | |
| 3.11 Examining the Stack Frame (`where', `up', `down', `frame') | Examining the stack frame (where, up, down, frame) | |
| 3.12 Stopping and Resuming Execution | Stopping and continuing (break, watch, step, cont...) | |
| 3.13 ruby-debug settings (`set args', `set autoeval'..) | rdebug-settings (set args, set autoeval, ...) | |
| 3.14 Program Information (`info') | Program Status (info) |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are several ways one can talk to ruby-debug and get
results. The simplest way is via a command-line interface directly
talking to the debugger. This is referred to below as a "Local
Interface". It's also possible to run the debugger and set up a port
by which some other process can connect and control the debug
session. This is called a "Remote Interface". When you want to gain
access to a remote interface you need to run ruby-debug using a
"Control Interface". This interface might not be the same process as
the process running the debugged program and might not even be
running on the same computer.
Other front-ends may use one of these and build on top and provide other (richer) interfaces. Although many of the commands are available on all interfaces some are not. Most of the time in this manual when we talk about issuing commands describing the responses elicited, we'll assume we are working with the local interface.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Usually a command is put on a single line. There is no limit on how long
it can be. It starts with a command name, which is followed by
arguments whose meaning depends on the command name. For example, the
command step accepts an argument which is the number of times to
step, as in step 5. You can also use the step command with no
arguments. Some commands do not allow any arguments.
Multiple commands can be put on a line by separating each with a
semicolon (;).
A blank line as input (typing just <RET>) means to repeat the previous command.
In the "local" interface, the Ruby Readline module is used. It
handles line editing and retrieval of previous commands. Up arrow, for
example moves to the previous debugger command; down arrow moves to
the next more recent command (provided you are not already at the last
command). Command history is saved in file .rdebug_hist. A
limit is put on the history size. You can see this with the show
history size command. See Command History Parameters for history parameters.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In the command-line interface, when ruby-debug is waiting for
input it presents a prompt of the form
(rdb:x). If debugging locally, x will be
the thread number. Usual the main thread is 1, so often you'll see
(rdb:1). In the control interface though x will be
ctrl and in post-mortem debugging post-mortem.
In the local interface, whenever ruby-debug gives an error
message such as for an invalid command, or an invalid location
position, it will generally preface the message with
***. However if annotation mode is on that the message is put
in a begin-error annotation and no *** appears.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
| 3.4.1 Help on Subcommands |
Once inside ruby-debug you can always ask it for information on
its commands, using the command help.
helphYou can use help (abbreviated h) with no arguments to
display a short list of named classes of commands:
(rdb:1) help ruby-debug help v0.10.1 Type 'help <command-name>' for help on a specific command Available commands: backtrace delete enable help next quit show undisplay break disable eval info p reload source up catch display exit irb pp restart step var condition down finish list ps save thread where continue edit frame method putl set trace |
help commandWith a command name as help argument, ruby-debug
information on how to use that command.
(rdb:1) help list ruby-debug help v0.10.0 l[ist] list forward l[ist] - list backward l[ist] = list current line l[ist] nn-mm list given lines * NOTE - to turn on autolist, use 'set autolist' (rdb:1) |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A number of commands have many sub-parameters or
subcommands. These include info, set,
show, enable and disable.
When you ask for help for one of these commands, you will get help for
all of the subcommands that that command offers. Sometimes you may
want help that subcommand and to do this just follow the command with
its subcommand name. For example help set annotate will just
give help about the annotate command. Furthermore it will give longer
help than the summary information that appears when you ask for
help. You don't need to list the full subcommand name, but just enough
of the letters to make that subcommand distinct from others will
do. For example, help set an is the same as help set annotate.
Some examples follow.
(rdb:1) help info Generic command for showing things about the program being debugged. -- List of info subcommands: -- info args -- Argument variables of current stack frame info breakpoints -- Status of user-settable breakpoints info catch -- Exceptions that can be caught in the current stack frame info display -- Expressions to display when program stops info file -- Info about a particular file read in info files -- File names and timestamps of files read in info global_variables -- Global variables info instance_variables -- Instance variables of the current stack frame info line -- Line number and file name of current position in source file info locals -- Local variables of the current stack frame info program -- Execution status of the program info stack -- Backtrace of the stack info thread -- List info about thread NUM info threads -- information of currently-known threads info variables -- Local and instance variables of the current stack frame |
(rdb:1) help info breakpoints Status of user-settable breakpoints. Without argument, list info about all breakpoints. With an integer argument, list info on that breakpoint. |
(rdb:1) help info br Status of user-settable breakpoints. Without argument, list info about all breakpoints. With an integer argument, list info on that breakpoint. |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
| 3.5.1 Quit (`quit') | Quitting the debugger (quit) | |
| 3.5.2 Restart (`restart') | Restarting Script execution (restart) | |
| 3.5.3 Interrupt (`interrupt') | Interrupting the debugger (interrupt) | |
| 3.5.4 Running Debugger Commands (`source') | Running Debugger commands (source) |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
quit [unconditionally]exitqTo exit ruby-debug, use the quit command (abbreviated
q), or alias exit.
A simple quit tries to terminate all threads in effect.
Normally if you are in an interactive session, this command will prompt to ask if you really want to quit. If you don't want any questions asked, enter the "unconditionally".
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
restartR Restart the program. This is is a re-exec - all debugger state is lost. If command arguments are passed those are used. Otherwise the last program arguments used in the last invocation are used.
In not all cases will you be able to restart the program. First, the program should have been invoked at the outset rather than having been called from inside your program or invoked as a result of post-mortem handling.
Also, since this relies on the the OS exec call, this command
is available only if your OS supports that exec; OSX for
example does not (yet).
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
interruptiInterrupt the program. Useful if there are multiple threads running.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
source filenameExecute the command file filename.
The lines in a command file are executed sequentially. They are not printed as they are executed. If there is an error, execution proceeds to the next command in the file. For information about command files that get run automatically on startup, see section Command files.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
If you find that you want to print the value of an expression frequently (to see how it changes), you might want to add it to the automatic display list so that ruby-debug evaluates a statement each time your program stops or the statement is shown in line tracing. Each expression added to the list is given a number to identify it; to remove an expression from the list, you specify that number. The automatic display looks like this:
(rdb:1) display n 1: n = 3 |
This display shows item numbers, expressions and their current values. If the expression is undefined or illegal the expression will be printed but no value will appear.
(rdb:1) display undefined_variable 2: undefined_variable = (rdb:1) display 1/0 3: 1/0 = |
Note: this command uses to_s to in expressions; for example an
array [1, 2] will appear as 12. For some datatypes like
an Array, you may want to call the inspect method, for example
display ARGV.inspect rather than display ARGV.
display exprAdd the expression expr to the list of expressions to display each time your program stops or a line is printed when linetracing is on (see section Executing expressions on stop (`display', `undisplay')).
displayDisplay the current values of the expressions on the list, just as is done when your program stops.
undisplay [num]delete display numRemove item number num from the list of expressions to display.
info displayShow all display expressions
disable display dnums…Disable the display of item numbers dnums. A disabled display item is not printed automatically, but is not forgotten. It may be enabled again later.
enable display dnums…Enable display of item numbers dnums. It becomes effective once again in auto display of its expression, until you specify otherwise.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
One way to examine and change data in your script is with the
eval command (abbreviated p). A similar command is
pp which tries to pretty print the result. Finally irb is
useful when you anticipate examining or changing a number of things,
and prefer not to have to preface each command, but rather work as one
does in irb.
| 3.7.1 Printing an expression (`eval', `p') | eval or print an expression (eval, p) | |
| 3.7.2 Pretty-Printing an expression (`pp', `putl', `ps')) | pretty print an expression (pp, ps, putl) | |
| 3.7.3 Run irb (`irb') | running irb using the current context |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
eval exprp exprUse eval or p to evaluate a Ruby expression, expr,
same as you would if you were in irb. If there are many expressions
you want to look at, you may want to go into irb from the debugger.
(rdb:p) p n
3
(rdb:1) p "the value of n is #{n}"
"the value of n is 3"
(rdb:1)
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ppEvaluates and pretty-prints expr
(rdb:1) p $LOAD_PATH ["/home/rocky/lib/ruby", "/usr/lib/ruby/site_ruby/1.8", "/usr/lib/ruby/site_ruby/1.8/i586-linux", "/usr/lib/ruby/1.8"] (rdb:1) pp $LOAD_PATH ["/home/rocky/lib/ruby", "/usr/lib/ruby/site_ruby/1.8", "/usr/lib/ruby/site_ruby/1.8/i586-linux", "/usr/lib/ruby/1.8"] |
putlIf the value you want to print is an array, sometimes a columnized list looks nicer:
(rdb:1) putl $LOAD_PATH /home/rocky/lib/ruby /usr/lib/ruby/site_ruby/1.8 /usr/lib/ruby/site_ruby/1.8/i586-linux /usr/lib/ruby/1.8 |
Note however that entries are sorted to run down first rather than
across. So in the example above the second entry in the list is
/usr/lib/ruby/site_ruby/1.8/i586-linux and the third entry is
/usr/lib/ruby/site_ruby/1.8.
If the value is not an array putl will just call pretty-print.
psSometimes you may want to print the array not only columnized, but
sorted as well. The list of debugger help commands appears this way,
and so does the output of the method commands.
(rdb:1) ps Kernel.private_methods Digest initialize y Pathname initialize_copy Rational location_of_caller active_gem_with_options method_added alias_method method_removed append_features method_undefined attr module_function attr_accessor private attr_reader protected attr_writer public class_variable_get remove_class_variable class_variable_set remove_const define_method remove_instance_variable extend_object remove_method extended singleton_method_added gcd singleton_method_removed gem_original_require singleton_method_undefined include timeout included undef_method |
If the value is not an array, ps will just call pretty-print.
See also the methods.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
irbRun an interactive ruby session (irb) with the bindings
environment set to the state you are in the program.
When you leave irb and go back to the debugger command prompt we show
again the file, line and text position of the program in the same way
as when entered the debugger. If you issue a list without
location information, the default location used is the current line
rather than the position may have gotten updated via a prior
list command.
triangle.rb:4
def triangle(n)
(rdb:1) list
[-1, 8] in /home/rocky/ruby/triangle.rb
1 #!/usr/bin/env ruby
2 # Compute the n'th triangle number - the hard way
3 # triangle(n) == (n * (n+1)) / 2
=> 4 def triangle(n)
5 tri = 0
6 0.upto(n) do |i|
7 tri += i
8 end
irb
>> (0..6).inject{|sum, i| sum +=i}
=> 21
>> exit
triangle.rb:4
def triangle(n)
(rdb:1) list # Note we get the same line range as before going into irb
[-1, 8] in /home/rocky/ruby/triangle.rb
1 #!/usr/bin/env ruby
2 # Compute the n'th triangle number - the hard way
3 # triangle(n) == (n * (n+1)) / 2
=> 4 def triangle(n)
5 tri = 0
6 0.upto(n) do |i|
7 tri += i
8 end
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
var const objectShow the constants of object. This is basically listing
variables and their values in object.constant.
var instance objectShow the instance variables of object. This is basically listing
object.instance_variables.
info instance_variablesShow instance_variables of @self
info localsShow local variables
info globalsShow global variables
info variablesShow local and instance variables of @self
method instance objectShow methods of object. Basically this is the same as running
ps object.instance_methods(false) on object.
method iv objectShow method instance variables of object. Basically this is the same as running
obj.instance_variables.each do |v|
puts "%s = %s\n" % [v, obj.instance_variable_get(v)]
end
|
on object.
method class-or-moduleShow methods of the class or module, class-or-module. Basically
this is the same as running ps object.methods on class-or-module.
on class-or-module.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ruby-debug can print parts of your script's source. When your script stops, ruby-debug spontaneously prints the line where it stopped and the text of that line. Likewise, when you select a stack frame (see section Selecting a frame (`up', `down', `frame')) ruby-debug prints the line where execution in that frame has stopped. Implicitly there is a default line location. Each time a list command is run that implicit location is updated, so that running several list commands in succession shows a contiguous block of program text.
You can print other portions of source files by giving an explicit position as a parameter to the list command.
If you use ruby-debug through its Emacs interface, you may prefer to use Emacs facilities to view source.
To print lines from a source file, use the list command
(abbreviated l). By default, ten lines are printed. Fewer may
appear if there fewer lines before or after the current line to center
the listing around.
There are several ways to specify what part of the file you want to print.
Here are the forms of the list command.
list line-numberl line-numberPrint lines centered around line number line-number in the current source file.
listlPrint more lines. If the last lines printed were printed with a
list command, this prints lines following the last lines
printed; however, if the last line printed was a solitary line printed
as part of displaying a stack frame (see section