Debugging

The default Ruby debugger allows you to set breakpoints and watchpoints and evaluate variables while your programs execute. To run a program in the debugger, use the -r debug option (where -r means “require” and debug is the name of the debugging library) when you start the Ruby interpreter. For example, this is how you would debug a program called debug_test.rb:

ruby -r debug  debug_test.rb

Once the debugger has started, you can enter various commands to step through your code, set breakpoints to cause the execution to pause at specific lines, set watches to monitor the values of variables, and so on. The following are the available debugging commands:

b[reak] [file|class:]<line|method> and b[reak] [file|class:]<line|method>

Sets breakpoint to some position

b[reak] [class.]<line|method>

Sets breakpoint to some position

wat[ch] <expression>

Sets watchpoint to some expression

cat[ch] <an Exception>

Sets catchpoint to an exception

b[reak]

Lists breakpoints

cat[ch]

Shows catchpoint

del[ete][ nnn]

Deletes some or all breakpoints

disp[lay] <expression>

Adds expression to display expression list

undisp[lay][ nnn]

Deletes one particular or all display expressions

c[ont]

Runs until end or breakpoint

s[tep][ nnn]

Steps (into code) one line or to line nnn

n[ext][ nnn]

Goes over one line or until line nnn

w[here]

Displays frames

f[rame]

Is the alias for where

l[ist][ (-|nn-mm)]

Lists program, lists backward nn-mm, lists given lines

up[ nn]

Moves to higher frame

down[ nn]

Moves to lower frame

fin[ish]

Returns to outer frame

tr[ace] (on|off)

Sets trace mode of current thread

tr[ace] (on|off) all

Sets trace mode of all threads

q[uit]

Exits from debugger

v[ar] g[lobal]

Shows global variables

v[ar] l[ocal]

Shows local variables

v[ar] i[nstance] <object>

Shows instance variables of object

v[ar] c[onst] <object>

Shows constants of object

m[ethod] i[nstance] <obj>

Shows methods of object

m[ethod] <class|module>

Shows instance methods of class or module

th[read] l[ist]

Lists all threads

th[read] c[ur[rent]]

Shows current thread

th[read] [sw[itch]] <nnn>

Switches thread context to nnn

th[read] stop <nnn>

Stops thread nnn

th[read] resume <nnn>

Resumes thread nnn

p expression

Evaluates expression and prints its value

h[elp]

Prints this help

<everything else>

Evaluates

Let’s see how a few of these commands might be used in a real debugging session. Open a system prompt, and navigate to the directory containing the file debug_test.rb, which is supplied in the sample code for this chapter. Start the debugger by entering this:

debug_test.rb

ruby -r debug debug_test.rb

Now, let’s try a few commands. In these examples, I’ve written [Enter] to show that you should press the enter key after each command. First let’s see a code listing (here note that l is a lowercase L character):

l [Enter]

You should see this, which is a partial listing of the file debug_test.rb:

debug_test.rb:2:          class Thing
(rdb:1) l
[-3, 6] in debug_test.rb
   1      # Thing
=> 2      class Thing
   3
   4              attr_accessor( :name )
   5
   6              def initialize( aName )
(rdb:1)

Note

If you see a listing from a file called ubygems.rb at this point instead of your program, refer to Ubygems? What’s Ubygems? in Ubygems? What’s Ubygems? for ways of correcting this problem.

The l you entered is the “list” command, which instructs the debugger to list the code in bite-sized chunks. The actual number of lines will vary with the code being debugged. Let’s list some more:

l [Enter]
l [Enter]

Now list a specific number of lines. Enter the letter l followed by the digit 1, a hyphen, and 100:

l 1-100 [Enter]

Let’s put a breakpoint on line 78:

b 78 [Enter]

The Ruby debugger should reply with this:

Set breakpoint 1 at debug_test.rb:78

You might also set one or more watchpoints. A watchpoint can be used to trigger a break on a simple variable (for example, entering wat @t2 would break when the @t2 object is created); or it may be set to match a specific value (for example, i == 10). Here I want to set a watchpoint that breaks when the name attribute of @t4 is “wombat”. Enter this:

wat @t4.name == "wombat" [Enter]

The debugger should confirm this:

Set watchpoint 2:@t4.name == "wombat"

Notice the watchpoint number is 2. You’ll need that number if you subsequently decide to delete the watchpoint. Okay, so now let’s continue (c) execution:

c [Enter]

The program will run until it hits the breakpoint. You will see a message similar to the following:

Breakpoint 1, toplevel at debug_test.rb:78
debug_test.rb:78:         puts("Game start" )

Here it shows the line number it’s stopped on and the code on that line. Let’s continue:

c [Enter]

This time it breaks here:

Watchpoint 2, toplevel at debug_test.rb:85
debug_test.rb:86:         @t5 = Treasure.new("ant", 2)

This is the line immediately following the successful evaluation of the watchpoint condition. Check that by listing the line number indicated:

l 86

The debugger shows a set of lines with the current line of execution (86) preceded by the => marker:

[81, 90] in debug_test.rb
   81     @t1 = Treasure.new("A sword", 800)
   82     @t4 = Treasure.new("potto", 500 )
   83     @t2 = Treasure.new("A dragon Horde", 550)
   84     @t3 = Treasure.new("An Elvish Ring", 3000)
   85     @t4 = Treasure.new("wombat", 10000)
=> 86     @t5 = Treasure.new("ant", 2)
   87     @t6 = Treasure.new("sproggit", 400)
   88
   89     #   ii) Rooms
   90     @room1 = Room.new("Crystal Grotto", [])

As you can see, line 86 contains the code that matches the watchpoint condition. Notice that execution did not stop after line 82, where @t4 was originally created, because the watchpoint condition was not met there (its name attribute was “potto” and not “wombat”). If you want to inspect the value of a variable when paused at a breakpoint or watchpoint, just enter its name. Try this:

@t4 [Enter]

The debugger will display the following:

#<Treasure:0x315617c @value=10000, @name="wombat">

You can similarly enter other expressions to be evaluated. Try this:

@t1.value [Enter]

This shows 800.

Or enter some arbitrary expression such as this:

10+4/2 [Enter]

This shows 12.

Now delete the watchpoint (recall that its number is 2):

del 2 [Enter]

And continue until the program exits:

c [Enter]

You can use many more commands to debug a program in this way, and you may want to experiment with those shown in the table given earlier. You can also view a list of commands during a debugging session by entering help or just h:

h [Enter]

To quit a debugging session, enter quit or q:

q [Enter]

Although the standard Ruby debugger has its uses, it is far from as simple or convenient to use as one of the graphical debuggers provided by integrated development environments. Moreover, it is quite slow. In my view, it is fine for debugging simple scripts but cannot be recommended for debugging large and complex programs.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.37.20