调试
默认的 Ruby 调试器允许你在程序执行时设置断点和监视点并计算变量。要在调试器中运行程序,请在启动 Ruby 解释器时使用 -r debug
选项(其中 -r
表示 ‘require’,debug
是调试库的名称)。例如,这是调试一个名为 debug_test.rb 的程序的方法:
ruby –r debug debug_test.rb
Ubygems?什么是 Ubygems …?
在某些情况下,如果运行上述命令,你可能会看到类似于以下令人费解的消息: c:/ruby/lib/ruby/site_ruby/1.8/ubygems.rb:4:require ‘rubygems’当你开始调试时,你会发现自己试图调试文件 ‘ubygems.rb’ 而不是你的程序!这似乎是一个困扰使用一键安装程序安装 Ruby 的 Windows 用户的主要问题:(http://rubyforge.org/projects/rubyinstaller/)此安装程序设置环境变量RUBYOPT=-rubygems
。在大多数情况下,这具有允许 Ruby 程序使用 ruby gems “打包系统”来安装 Ruby 库的理想效果。但是,当你尝试使用 -r
选项时,会将其解释为 -r ubygems
,这就是加载文件 ubygems.rb 的原因。Ruby 顺便(可能令人困惑?)提供了一个名为 ubygems.rb 的文件,它除了引入(requiring)rubygems.rb 之外什么都不做!有两种方法可以解决这个问题。你可以永久删除 RUBYOPT
,也可以暂时禁用它。但是,如果你选择永久删除它,则以后使用 ruby gems 时可能会遇到副作用。要永久删除它,请加载“开始”菜单,(如果使用 XP 则为“设置”)“控制面板”;(如果使用 Vista,则为“系统和维护”);单击系统(在 Vista 上,你现在应该单击“高级系统设置”);在“系统属性”对话框中,选择“高级”选项卡;单击环境变量;在“系统变量”面板中,找到 RUBYOPT
并删除它。更安全的替代方法是在加载调试器之前在命令提示符处禁用该变量。为此,请输入: set RUBYOPT=这将仅为此命令会话禁用 RUBYOPT
环境变量。你可以输入以下命令验证这一点: set RUBYOPT你应该会看到以下消息: Environment variable RUBYOPT not defined但是,打开另一个命令窗口并输入 set RUBYOPT
,你将看到此处的环境变量保留其默认值。一旦调试器启动后,你可以输入各种命令来逐步执行代码,设置断点以使执行暂停在特定行,设置监视以监视变量值等等。在下一页是可用的调试命令列表:
命令 | 解释说明 |
---|---|
b[reak] [file|class:]<line|method> | 在某个位置设置断点 |
b[reak] [class.]<line|method> | 在某个位置设置断点 |
wat[ch] <expression> | 为某个表达方式设置监视点 |
cat[ch] <an Exception> | 为异常设置捕获点 |
b[reak] | 列出断点 |
cat[ch] | 显示捕获点 |
del[ete][ nnn] | 删除部分或全部断点 |
disp[lay] <expression> | 将表达式添加到显示表达式列表 |
undisp[lay][ nnn] | 删除一个特定或所有显示表达式 |
c[ont] | 运行到结束或遇到断点 |
s[tep][ nnn] | 前进(代码)1 行或 nnn 行 |
n[ext][ nnn] | 跨越一行或直到 nnn 行 |
w[here] | 显示帧 |
f[rame] | where 别名 |
l[ist][ (-|nn-mm)] | 程序列表,- 向后列出给定行 nn-mm 的列表 |
up[ nn] | 移到更大的帧 |
down[ nn] | 移到更小的框帧 |
fin[ish] | 回到外部帧 |
tr[ace] (on|off) | 设置当前线程为跟踪模式 |
tr[ace] (on|off) all | 设置所有线程为跟踪模式 |
q[uit] | 退出调试器 |
v[ar] g[lobal] | 显示全局变量 |
v[ar] l[ocal] | 显示局部变量 |
v[ar] i[nstance] <object> | 显示对象的实例变量 |
v[ar] c[onst] <object> | 显示对象的常量 |
m[ethod] i[nstance] <obj> | 显示对象的方法 |
m[ethod] <class|module> | 显示类或模块的实例方法 |
th[read] l[ist] | 列出所有线程 |
th[read] c[ur[rent]] | 列出当前线程 |
th[read] [sw[itch]] <nnn> | 将线程上下文切换为 nnn |
th[read] stop <nnn> | 停止线程 nnn |
th[read] resume <nnn> | 恢复线程 nnn |
p expression | 计算表达式并打印其值 |
h[elp] | 打印帮助信息 |
<everything else> | 执行计算 |
让我们看看如何在真正的调试会话中使用其中一些命令。打开系统提示符并导航到包含文件 debug_test.rb 的目录。输入以下命令启动调试器:
ruby –r debug debug_test.rb
现在,让我们尝试一些命令。 在这些示例中,我写了 [Enter] 以显示你应该在每个命令后按 Enter 键。首先让我们看一下代码列表:
l [Enter]
这显示了该程序的前几行。l
(小写 “L”)或 list
命令列会出小块代码。实际行数将随调试代码而变化。列出更多:
l [Enter]
l [Enter]
或列出特定行数(此处字母 ‘l’ 后跟数字 1,连字符和 100):
l 1-100 [Enter]
我们在第 78 行放一个断点(breakpoint):
b 78 [Enter]
Ruby 调试器应该回复:
Set breakpoint 1 at debug_test.rb:78
我们也可能设置一个或多个监视点(watchpoints)。监视点可用于触发简单变量的中断(例如,当创建 @t2
对象时,输入 wat @t2
会中断);或者它可以设置为匹配特定值(例如 i == 10
)。在这里,我想设置一个在 @t4
的 name
属性为 “wombat” 时中断的监视点:
wat @t4.name == "wombat" [Enter]
调试器应该确认这一点:
Set watchpoint 2:@t4.name == "wombat"
请注意观察点编号为 2.如果你随后决定删除监视点,则需要该编号。好的,现在让我们继续执行:
c [Enter]
程序将一直运行,直到它到达断点。你将看到类似于以下内容的消息:
Breakpoint 1, toplevel at debug_test.rb:78
debug_test.rb:78: puts( "Game start" )
这里显示了它停在的行号和该行的代码。让我们继续:
c [Enter]
这次它在这里中断了:
Watchpoint 2, toplevel at debug_test.rb:85
debug_test.rb:85: @t5 = Treasure.new("ant", 2)
这是在成功计算监视点条件之后的行。通过列出指示的行号来查看:
l 85
调试器高亮显示了一组行,在当前执行(86):
[80, 89] in debug_test.rb
80 # i) Treasures
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
如你所见,第 85 行包含与监视点条件匹配的代码。请注意,在最初创建 @t4
的第 82 行之后,执行没有停止,因为那里没有满足监视点条件(它的 name
属性是 “potto”,而不是 “wombat”)。如果要在断点或监视点处暂停时查看变量的值,只需输入其名称即可。试试这个:
@t4 [Enter]
调试器将显示:
#<Treasure:0x315617c @value=10000, @name="wombat">
你可以同样输入要执行的其它表达式:
@t1.value [Enter]
10+4/2 [Enter]
现在删除监视点(回想一下它的编号是 2):
del 2 [Enter]
并继续,直到程序退出:
c [Enter]
还有更多的命令可用于以这种方式调试程序,你可能想要尝试上表中显示的那些。你还可以通过输入 help
或 h
在调试会话期间查看命令列表:
h [Enter]
要退出调试会话,请输入 quit
或 q
:
q [Enter]
虽然标准的 Ruby 调试器有其用途,但它不如使用集成开发环境提供的图形调试器简单或方便。而且,它很慢。在我看来,调试简单脚本很好,但不建议用于调试大型和复杂的程序。