Ejecución de un Programa con el Depurador

También podemos usar el depurador para ejecutar el programa paso a paso. El depurador de Ruby se activa usando -rdebug:

~/rubytesting$ cat -n polar.rb 
     1	#!/usr/bin/env ruby
     2	
     3	def c2p(x, y) 
     4	  theta = Math.atan2(y, x)
     5	  r     = Math.hypot(x, y)
     6	  [r, theta]
     7	end
     8	x, y = 1, 1
     9	x, y = ARGV.map { |t| t.to_f }  if ARGV.length == 2 
    10	r, theta = c2p(x, y)
    11	
    12	puts "r = #{r} theta = #{theta}\n"

Para llamar al debugger:

~/rubytesting$ ruby -rdebug polar.rb 1 1
Debug.rb
Emacs support available.

polar.rb:3:def c2p(x, y)

Para pedir ayuda usamos h:

(rdb:1) help
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
(rdb:1)

Para evaluar una expresión:

(rdb:1) p 2*5
10
(rdb:1)

Para listar el programa:

(rdb:1) l
[-2, 7] in polar.rb
   1  
   2  
=> 3  def c2p(x, y) 
   4    theta = Math.atan2(y, x)
   5    r     = Math.hypot(x, y)
   6    [r, theta]
   7  end
(rdb:1) l
[8, 17] in polar.rb
   8  x, y = 1, 1
   9  x, y = ARGV.map { |t| t.to_f }  if ARGV.length == 2 
   10  r, theta = c2p(x, y)
   11  
   12  puts "r = #{r} theta = #{theta}\n"
(rdb:1)

Para ejecutar una sentencia:

(rdb:1) n
polar.rb:8:x, y = 1, 1
(rdb:1) 
n
polar.rb:9:x, y = ARGV.map { |t| t.to_f }  if ARGV.length == 2 
(rdb:1) x
1
(rdb:1) y
1
(rdb:1)

Para examinar una expresión:

(rdb:1) ARGV
["1", "1"]
(rdb:1) ARGV.length
2
(rdb:1) p "43".to_f
43.0

Para probar e investigar:

(rdb:1) puts "hello" if ARGV.length == 2
hello
nil
Para investigar el funcionamiento de map:
(rdb:1) [1,8, 9].map { |x| x*x }
[1, 64, 81]
(rdb:1)

La sentencia con el map es en realidad un bucle:

(rdb:1) n
polar.rb:9:x, y = ARGV.map { |t| t.to_f }  if ARGV.length == 2 
(rdb:1) n
polar.rb:9:x, y = ARGV.map { |t| t.to_f }  if ARGV.length == 2 
(rdb:1) n
polar.rb:9:x, y = ARGV.map { |t| t.to_f }  if ARGV.length == 2 
(rdb:1) n
polar.rb:10:r, theta = c2p(x, y)
Para entrar al método usamos s:
(rdb:1) s
polar.rb:4:  theta = Math.atan2(y, x)
(rdb:1) n
polar.rb:5:  r     = Math.hypot(x, y)
(rdb:1) p theta
0.785398163397448
Para salir de la rutina usamos finish que retorna al stackframe que envuelve al actual:
(rdb:1) fin
polar.rb:12:puts "r = #{r} theta = #{theta}\n"
Para continuar la ejecución hasta el siguiente punto de break usamos c:
(rdb:1) c
r = 1.4142135623731 theta = 0.785398163397448

Con b podemos poner un punto de break:

[~/rubytesting]$ ruby -rdebug polar.rb 
Debug.rb
Emacs support available.

polar.rb:3:def c2p(x, y) 
(rdb:1) l
[-2, 7] in polar.rb
   1  #!
   2  
=> 3  def c2p(x, y) 
   4    theta = Math.atan2(y, x)
   5    r     = Math.hypot(x, y)
   6    [r, theta]
   7  end
(rdb:1) l
[8, 17] in polar.rb
   8  x, y = 1, 1
   9  x, y = ARGV.map { |t| t.to_f }  if ARGV.length == 2 
   10  r, theta = c2p(x, y)
   11  
   12  puts "r = #{r} theta = #{theta}\n"
(rdb:1) b 4
Set breakpoint 1 at polar.rb:4
(rdb:1) c
Breakpoint 1, c2p at polar.rb:4
polar.rb:4:  theta = Math.atan2(y, x)
Con w podemos ver en que lugar estamos:
(rdb:1) w
--> #1 polar.rb:4:in `c2p'
    #2 polar.rb:10
(rdb:1)

Véase

Para saber mas sobre el debugger consulta:

  1. La sección Debugging, Depurando 86 de estos apuntes
  2. La sección When Trouble Strikes del libro Programming Ruby
  3. http://www.ibm.com/developerworks/opensource/tutorials/os-distruby/section3.html
  4. http://ruby.about.com/od/advancedruby/a/debugging.htm.



Subsecciones
Casiano Rodriguez León 2015-01-07