Hey, Don’t Dump. Debug!

Are the "Two Ps" (print statements and prayer) all that comprise your debugging strategy? It's time you were introduced to the Interactive Ruby Debugger.

I often ask other developers for advice. At times, the counsel reinforces my approach; at other times, the guidance challenges my thinking, leading me to refine my code or even pursue a wholly different solution.

Out of curiosity, I also ask other coders about debugging techniques, and more often than not, I am surprised by the answer. Believe it or not, the vast majority relies on liberal “print” statements sprinkled throughout code. Of course, “print” takes many forms—dump pertinent data structures, emit trace statements to standard error, and log interim results in a separate file—and there are cases where these methods are mandated. Still, it puzzles me why more skilled developers do not use a debugger. Extensions to PHP allow for interactive forensics; Perl running within mod_perl supports debugging; and Ruby on Rails’s Mongrel provides the --debugger option to interrupt execution and drop to a debug console.

In my Rails work, I use the debugger extensively. The debugger combines the power of the Rails console and the Interactive Ruby Debugger, irb, and peers into running code responding to incoming requests. Better yet, I can yield to the debugger console anywhere—in a controller, a view, a plug-in or helper. Within the debugger, I can inspect the stack, variables, the params hash, and more.

Installing the Debugger

The debugger, ruby-debug, is provided as a Ruby gem and installs just as easily as any other extension.

$ sudo gem install ruby-debug

Once installed, you can invoke the debugger anywhere in your code with a call to debugger.

class ExampleController < ApplicationController
  def index
    # ...
    debugger
    # ...
   end
end

By default, Rails's script/server ignores calls to the debugger (and instead emits a message such as Debugger requested, but was not available). To enable the debugger and temporarily halt execution at each call, launch Mongrel with the option --debugger.

$ ruby ./script/server --debugger
=> Booting Mongrel
=> Rails 2.3.2 application starting on http://0.0.0.0:3001
=> Debugger enabled
=> Call with -d to detach
=> Ctrl-C to shutdown server

Once the debugger is enabled, each call to debugger generates a command prompt. The prompt is prefaced by the file name and line number where the call occurred and the next line of code to execute.

/Users/supergiantrobot/Projects/dc/trunk/app/controllers/search_controller.rb:32
@results = Part.uniqify( @results ) if logged_in?
(rdb:3)

(The 3 in the prompt is the thread number, which you can safely ignore if you're not juggling multiple threads.) At the prompt, you can type a number of commands to help ferret out your mistake. When in doubt, simply type help for a list of available commands or help command for hints about a specific command.

Commands to Query State

Like gdb (the Linux debugger for many languages) and Firebug (the Firefox debugger for JavaScript), rdb provides instructions to march through code and examine state. Here's an example using some of the most common commands.

The sample code prints the catalog of revisions made to records in the database. The controller is standard; the view is written in HAML, but could just as well be any other format. A call to debugger has been added at the start of the index action.

class RevisionController < ApplicationController
  before_filter :login_required

  def index
  	debugger

    @revisions = Revision.paginate :page => params[:page],
      :order => 'created_at DESC'
  end
end
%table
  - @revisions.each do |revision|
    %tr
      %td
        = revision.author.capitalize
      %td
        = revision.field
      %td
        = revision.value

The first command is list (which can be abbreviated to simple l, or lowercase L). It prints the ten lines of code surrounding the breakpoint to provide context.

.../app/controllers/revision_controller.rb:7
@revisions = Revision.paginate :page => params[:page],
(rdb:20) list
[2, 11] in .../app/controllers/revision_controller.rb
   2    before_filter :login_required
   3
   4    def index
   5      debugger
   6
=> 7      @revisions = Revision.paginate :page => params[:page],
   8        :order => 'created_at DESC'
   9    end
   10  end

The arrow (=>) reflects the program counter, or the statement about to execute. If you type list again, it shows the next ten lines of code.

The next command is print or p. It reveals the value of its argument, and formats the output as inspect would.

(rdb:20) p params
{"action"=>"index", "controller"=>"revision"}
(rdb:20) params
{"action"=>"index", "controller"=>"revision"}

Inspecting a variable is so common, there's a shortcut: omit print and simply type the name of the variable. That's the latter command above.

The backtrace command displays the call stack. The current frame—that is, the frame where you called debugger&mdashl;is numbered 0. Commands such print and list always apply to the current frame.

Preceding call frames are numbered 1, 2, and so on. Use the frame n command, where n is a frame number, to move to a specific frame. Again, an arrow (-->indicates your current frame.

(rdb:20) backtrace
--> #0 RevisionController.index
       at line .../app/controllers/revision_controller.rb:7
    #1 Kernel.send(e#NilClass)
       at line .../actionpack-2.3.2/lib/action_controller/base.rb:1322
    ...
    #44 Mongrel::HttpServer.run
       at line .../mongrel-1.1.5/lib/mongrel.rb:285
(rdb:20) frame 44
(rdb:20) list
[280, 289] in /opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb
   280                if worker_list.length >= @num_processors
   281                  STDERR.puts "Server overloaded with #{worker_list.length} processors (#@num_processors max). Dropping connection."
   282                  client.close rescue nil
   283                  reap_dead_workers("max processors")
   284                else
=> 285                  thread = Thread.new(client) {|c| process_client(c) }
   286                  thread[:started_on] = Time.now
   287                  @workers.add(thread)
   288
   289                  sleep @throttle if @throttle > 0
(rdb:20) backtrace
   #0 RevisionController.index
       at line /Users/supergiantrobot/Projects/dc/trunk/app/controllers/revision_controller.rb:7

...
--> #44 Mongrel::HttpServer.run
       at line .../mongrel-1.1.5/lib/mongrel.rb:285

By the way, if you want to know what instance variables are defined in the current frame, type instance_variables.

(rdb:20) frame 0
#0 RevisionController.index
       at line .../app/controllers/revision_controller.rb:7
(rdb:20) instance_variables
["@_params", "@request_origin", "@_request", "@search_options", "@performed_render", "@_headers", "@template", "@action_name", "@_response", "@url", "@performed_redirect", "@before_filter_chain_aborted", "@target", "@_session"]

You can also use the var command to query global variables, local variables, and constants and instance variables in any object.

(rdb:20) var global
$! = nil
...
$tcp_defer_accept_opts = nil
$~ = nil
(rdb:20) var local
  __dbg_verbose_save => false
  const_name => :Revision
  e => nil
  parent_qualified_name => nil
  qualified_name => nil
(rdb:20) var instance Inventory
@after_create_callbacks = [#<ActiveSupport::Callbacks::Callback:0x262f35c
@identifier=nil, @kind=:after...
...
@observer_peers = [#<StockObserver:0x25f4090>]
@parent_name = nil

Next: Commands to Control Execution

Comments on "Hey, Don’t Dump. Debug!"

grdetil

As a user and advocate of trace prints for debugging, here is why I think they remain a popular strategy. When you learn to program in a language, one of the first things you learn is how to get data out of the program. So, it’s a tool that’s always in the forefront of your mind when programming and debugging.

On the other hand, debuggers tend to be specific to a single OS and/or language, with a large set of arcane and cryptic commands that you need to learn on top of the language. And moving from one debugger to another is often more mind-warping than moving from one language to another. In the younger days of Unix, I had gotten to know a few tricks in db and adb, only to find that knowledge of no use in gdb on Linux. So, I’ve learned how to get a backtrace in gdb, only so I can more precisely target my trace prints by narrowing down the point of failure. I have yet to learn much more than that in gdb or any other recent debugger.

Reply

Definitely would love to start a website like yours. Wish I had the time. My site is so amateurish compared to yours, feel free to check it out: http://tinyurl.com/o55af8p Alex :)

Reply

Advise the bad! any time you attached ?????? ?? ?? but? Yangling frowned. Yangling eliminated ????? ????? ?? ???? ??? ?? ????? ????? ?? Una all set ??? ?????? hands and fingers, .

Reply

is experienced ??? ?????? ?????? injection therapy! really ????? ?? ?????? ample. . are not aware of exactly why? with Bavaria together with other ????? ????? ?? ?????? ?? our ?????? ?? ?????? {towns.

Reply

thank you for share!

Reply

thank you for share!

Reply

}, Just like push is absolutely not smallish ??? ??? ??. Forestry and even Mother Yue, Ning Brother, Paying attention to ?????? ?? ?? ???? ????? ??? that ???? ????? ?? peculiar scenario ???? ????? ??.

Reply

Hey, Don’t Dump. Debug! | Linux Magazine
ysbozefeso http://www.g6878qs0kncbx973c3l5u179tfo37e6as.org/
[url=http://www.g6878qs0kncbx973c3l5u179tfo37e6as.org/]uysbozefeso[/url]
aysbozefeso

Reply

Hey, Don’t Dump. Debug! | Linux Magazine

Reply

There are actually definitely loads of details like that to take into consideration. That’s a great point to bring up. I give the thoughts above as general inspiration but clearly you’ll find questions like the one you bring up exactly where the most essential factor might be working in honest fantastic faith. I don?t know if top practices have emerged about issues like that, but I am positive that your job is clearly identified as a fair game. Both boys and girls feel the impact of just a moment’s pleasure, for the rest of their lives.
jordans for cheap

Reply

Youre so cool! I dont suppose Ive read anything like this prior to. So nice to get somebody with some original thoughts on this subject. realy thank you for starting this up. this web site is some thing which is necessary on the internet, someone having a small originality. beneficial job for bringing some thing new to the world wide web!
cheap jordans shoes

Reply

Spot on with this write-up, I really feel this site requirements far more consideration. I’ll most likely be once more to read much more, thanks for that info.
shoes jordan

Reply

An impressive share, I just given this onto a colleague who was doing a bit analysis on this. And he the truth is purchased me breakfast because I identified it for him.. smile. So let me reword that: Thnx for the treat! But yeah Thnkx for spending the time to discuss this, I feel strongly about it and really like reading alot more on this topic. If feasible, as you turn into expertise, would you mind updating your weblog with extra details? It’s highly helpful for me. Massive thumb up for this weblog post!
cheapest jordans

Reply

Hey,

Stumbled upon your blog on Google and you definitely deserve more visitors!

Shared your blog on Facebook if that helps :)

Jared

Check out my site if you have time, maybe even share it on Facebook:
gta 5 cheats

Reply

Blog looks nice. I’m still trying to make a blog but it won’t be as professional as yours /: Keep on blogging :) pirater un compte facebook

Reply

roaring success ??? ??? ???. {nevertheless|although|nonetheless|however , for that reason ????? ????? ?? ??? ??????? and inform you. you will easily ????? ????? ?? look for ??? ?? ??? ??? ?? ??? Leader Chang, In actual fact.

Reply

beats held lure discovered to remove out of hatch

Z22 as well [url=http://www.autoarticle.co.uk/]Burberry handbags uk[/url] as simple to [url=http://www.trench-cover.co.uk/]Burberry Sale UK[/url] utilize, that score table features the credit score every golf hole. Whether it is Hunting for pockets or 18 holes, [url=http://www.activeplaygrounds.co.uk/]http://www.activeplaygrounds.co.uk/[/url] this unique little machine keeps count number to your overall standing. It might become accustomed to monitor exactly [url=http://www.autoarticle.co.uk/]Burberry handbags[/url] [url=http://www.scenepreston.co.uk/]Burberry bags sale uk[/url] how when you [url=http://www.purplebay.co.uk/]Burberry Handbags[/url] putt.

Absolutely yes, find something to help that you [url=http://www.tbpav.co.uk/]Burberry Outlet UK[/url] simply feel can make you try a back [url=http://www.raisecreative.co.uk/]http://www.raisecreative.co.uk/[/url] corner (locating a [url=http://www.scenepreston.co.uk/]Burberry bags outlet[/url] tote and also brief-case while in the back again). However , hardly ever, ever in your life, [url=http://www.canham-thomas.co.uk/]Burberry Bags Sale[/url] reckon that little one is definitely on my little intellect so this would not take place. Since i certain a great number [url=http://www.soukh-couture.co.uk/]Burberry Outlet[/url] of people father and mother notion so.

The explanation funny on the globe producing cases is usually that most people did anyone essentially applies real. Impression safeguard stuff inside out incidents that they 3 it is actually brand-new Italian textile is incredibly delicate. Nonetheless in effects.

[url=http://www.islearts.co.uk/]cheap beats by dre uk[/url]
[url=http://www.c-m-f.ca/]Louis Vuitton Handbags Canada[/url]
[url=http://www.wahun.org/]Tory Burch Outlet[/url]
[url=http://www.uldrive.co.uk/]Louboutin Outlet[/url]
[url=http://www.health-forum.us/]Cheap Louis Vuitton Bags[/url]
[url=http://www.theinsidescoop.us/]Cheap Christian Louboutin Shoes[/url]
[url=http://www.offerpages.co.uk/]cheap beats by dre uk[/url]
[url=http://www.andreafarmer.co.uk/]cheap beats by dre uk[/url]
[url=http://www.morocco4u.co.uk/]cheap beats by dre uk[/url]
[url=http://www.quarry-ltd.co.uk/]Louboutin Shoes UK[/url]
[url= http://www.rosetintedweb.co.uk/Louboutin uk[/url]
[url=http://www.easd.fr/]Sac Louis Vuitton Pas Cher[/url]
[url=http://www.surfworx.co.uk/]Cheap Beats by Dre[/url]
[url=http://www.fcih.org/]http://www.fcih.org/[/url]
[url=http://www.amhcasc.org/]http://www.amhcasc.org/[/url]
[url=http://www.marianna.us/]http://www.marianna.us/[/url]
[url=http://www.bscta.co.uk/]http://www.bscta.co.uk/[/url]
[url=http://www.hluxury.ca/]http://www.hluxury.ca/[/url]
[url=http://www.daysoutatlas.co.uk/]Louboutin Outlet UK[/url]
[url=http://www.cakesandsweets.co.uk/]Jimmy Choo Shoes Uk[/url]
[url=http://www.thaiontheriver.co.uk/]Jimmy Choo outlet Uk[/url]
[url=http://www.sagittariuspro.com/]Cheap Christian Louboutin Shoes[/url]
[url=http://www.bustyasian.us/]Cheap Christian Louboutin[/url]
[url=http://www.glencocatering.co.uk/]Louis Vuitton Outlet UK[/url]
[url=http://www.germanphysiks.co.uk/]Louis Vuitton Outlet UK[/url]
[url=http://www.eftcambridge.co.uk/]Louis Vuitton bags UK[/url]
[url=http://www.plumpstudios.co.uk/]http://www.plumpstudios.co.uk/[/url]
[url=http://www.blauerdiamant.com/]cheap Michael Kors[/url]
[url=http://www.lqvc.ca/]Michael Kors Handbags[/url]
[url=http://www.sportszineuk.co.uk/]Jimmy Choo Outlet[/url]
[url=http://www.provalis.co.uk/]Louis Vuitton Outlet UK[/url]
[url=http://www.batp.us/]Christian Louboutin Outlet Online[/url]
[url=http://www.smallcities.us/]Cheap Christian Louboutin Shoes Sale[/url]
[url=http://www.obie.ca/]Christian Louboutin Canada[/url]
[url=http://www.curators.us/]Christian Louboutin Outlet[/url]
[url=http://www.lissymoedl.de/]Christian Louboutin Onlineshop[/url]
[url=http://www.avenue35.co.uk/]Giuseppe Zanotti Sneakers[/url]
[url=http://www.wwdl.org/]Cheap Louis Vuitton Bgas[/url]
[url=http://www.fansusa.org/]Louis Vuitton Outlet Online[/url]

Reply

thank you for share!

Reply

???, As per notes classics,Blink connected with an ???? ????? ?? attention ??? ?????? ??? Once oakley ?? ???? ????? ?? a lot of money, such as experience of quite a few bloodthirsty Wow in advance of ???? ????? ???.

Reply

Rejoicing underneath the Lich {Queen|California king|Full|Double|Ruler|Important|Cal . has changed into a ???? ??? ?????? ????? ?????? ?? ??? ?????? ?? zombie. ?t had been also later part of the ??? ?? ??! it goes without mention ??? ?? ????? the particular encounter, critical taken.

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>