ruby 调试
关于Ruby的一个误解在Ruby社区内部和外部都非常普遍。 误解是:Ruby没有调试器。 有人认为这是Ruby的问题。 其他人试图将这种缺乏调试工具的现象解释为明智和良好的作风 。
但是,无论从哪个角度来看:这仍然是一个误解 。 Ruby确实有调试工具-其实不少。 让我们看一下各种Ruby实现中的可用工具,包括调试GUI,调试器实现和调试支持。
什么是调试器?
首先,让我们澄清一下“调试器”的实际含义。
调试GUI和界面
当然, 交互式调试器最重要的部分(至少对于用户而言)是用户界面。
提供了用于Ruby调试器的命令行界面,例如Ruby标准库Rubinius调试器附带的命令行界面。
尽管这些当然可以调试代码,但是它们也使设置断点或查看实际情况变得很繁琐。
集成开发环境。
集成部分对于调试很重要,因为IDE可以集成代码编辑和调试工具。
可以直接在源代码编辑器中完成断点的管理-与获取一段代码的行号,转到命令行调试器并在此手动输入断点相比。
基于IDE的行(例如基于行的步进)功能也变得更加有用,该IDE在正确的行处打开当前堆栈帧的文件。
EclipseMonkey扩展允许使用JRuby编写脚本 。
由于这些脚本与Eclipse IDE在同一JVM中运行,因此可以访问Debugger实例并对其进行控制。
调试器协议或连接到后端
将调试器用户界面(如IDE)与调试器后端连接的一种简单方法是使用命令行界面,并通过stdin / stdout / stderr流进行控制。
这样,编辑器或IDE的调试器支持可以控制调试器,但同时使用户更容易管理断点。
telnet
并连接到Ruby调试器。
debug-commons和
DBGp命令中的协议由单行字符串和XML响应组成。
虚拟机支持或调试后端
为了允许诸如断点之类的功能起作用, 语言运行时必须至少提供最少的支持来监视和控制执行。
这可以像Ruby的跟踪功能一样小:在执行一行Ruby代码之前,Ruby会调用一个通过调用
set_trace_func
设置的回调函数。
传递给此函数的参数包括有关Ruby即将执行的代码行的环境的信息,例如它的行号,所在文件的名称,其类等。这足以实现断点功能 :file名称和行号允许检查已注册断点的列表,如果该行已注册一个。
只是通过不从回调返回而暂停 -Ruby运行时只能在回调返回后才能继续。
在此基础上,可以实现步进等功能。
在断点行的位置修改加载的代码 (无论是AST还是操作码) 。
某些语言运行时具有内置的调试支持,该调试支持与其执行机制集成在一起。
Java和.NET二进制文件都可以附带调试信息(即,从文件和行号到字节码中位置的映射),然后内置调试支持将其用于实现调试器功能。
例如,在Java空间中,JVM附带了用于访问此功能的
JVM工具接口(JVM TI )和用于连接到JVM的
Java调试线协议(JDWP )。
Rubinius调试器,它使用Ruby代码的可访问和可修改的操作码(Rubinius在执行之前将Ruby源代码编译为操作码)。
通过将常规操作码与特殊操作码交换来设置断点,该特殊操作码会挂起当前线程并通知调试器堆栈的更高层。
Ruby实现的调试器和IDE支持
通过基本设置,让我们看一下可用的东西,首先从Matz的Ruby实施(MRI)开始 ,这是最常用和受支持的Ruby实施。
之后,我们将研究JRuby,Rubinius和IronRuby的情况-这些Ruby实现的工具支持以及它们与MRI不同的地方,无论是工具支持还是性能。
Ruby/核磁共振
调试后端
Ruby 1.8.x或MRI是用C编写的官方Ruby解释器。此版本的Ruby提供了许多调试选项。
跟踪调试器可用,标准库附带其Ruby版本。
但是,有更快的实现方式。
一种是
ruby-debug ,它是使用本机扩展实现的。
Steel IDE中的Ruby :
Cylon调试器 。
它还使用本机代码来实现,以实现该功能,并使用Ruby钩子来获取有关方法调用等事件的通知。根据
SapphireSteel的基准测试 ,Cylon调试器明显比用Ruby编写的调试器快,也比ruby-调试。
图形用户界面
许多Ruby IDE提供调试支持。
基于Eclipse的
RDT(现在是Aptana和RadRails的一部分)已经有很长时间的调试支持,首先连接到基于Ruby的跟踪调试器,然后再支持ruby-debug。
RDT的调试协议已被
纳入 Netbeans Ruby中用于提供调试
的debug-commons项目中。
Ruby IDE空间中的另一个旧计时器是
ActiveState的Komodo ,它基于
DBGp协议构建以连接到其协议。
Eclipse DLTK Ruby (也是
CodeGear 3dRail的基础)是另一个利用Eclipse调试器GUI的IDE。
DLTK还使用DBGp连接到后端。
SapphireSteel的Ruby in Steel包含调试器GUI,可使用其Cylon调试器进行快速调试。
IntelliJ Ruby Roadmand将调试支持列为未来的项目 。
Ruby
调试后端
基于常规跟踪的Ruby调试器也可以在JRuby中使用。
此外,还有一个更快的版本
jruby-debug (也托管在debug-commons项目中)使用Java作为实现语言,而不是Ruby,以减少每行执行的开销。
JRuby调试后端来自SapphireSteel 。
已经以其定制的MRI快速Cylon调试器提及了该公司。
与jruby-debug不同,SapphireSteel的解决方案使用Java和本地代码(通过JNI)作为调试器后端。
图形用户界面
支持
set_trace_func
调试的Ruby IDE也可以与JRuby一起使用,Netbeans和Apatana也附带jruby-debug支持。
跨语言调试支持显然为每个使用JRuby的人带来了额外的好处,这些人不仅将JRuby用作普通的Ruby运行时,而且使用Ruby编写Java类脚本。
在这种情况下,跨语言调试很有用-即在Ruby代码调用Java代码时显示Ruby和Java堆栈以及变量。
鲁比尼乌斯
调试后端
Rubinius当然已经走了很长一段路-特别是在过去的几个月中,就调试性能而言,它的调试支持从不存在跃居到Ruby领域的前端。
全速Ruby调试器允许运行启用了调试的Ruby程序,而没有其他解决方案的性能开销,如上所述或在链接的新闻中。
可访问已加载的Ruby代码的
ParseTree以及
堆栈跟踪 。
内省功能进一步扩展,例如使用
SendSites 。
SendSites代表消息发送的站点(“方法调用”),并且可以链接到该方法。
这样可以在运行时确定已加载代码的配置,而且还可以作为概要分析或代码覆盖工具。
每个发送的消息都会增加SendSite的计数器;
由于此信息可用于常规Ruby代码,因此编写简单的探查器或至少一个代码覆盖率工具仅需几行代码。
图形用户界面
目前,Rubinius调试器的用户界面是命令行界面,该界面可以管理断点,单步执行,还可以查看运行Ruby代码或其源文件的操作码。
有用的命令是
sexp [method]
,它返回
[method]
的AST的ParseTree s-expr表示形式。
(忽略该参数会将当前方法的AST显示为ParseTree s-expr)。
这是非常有用的信息,特别是对于使用元编程的代码-运行时生成的代码显然没有
源代码。
能够查看生成的已加载代码可以帮助调试执行
元编程的代码。
查看s-expr是从尝试猜测所生成的代码的作用而迈出的一步-通过回退基于ParseTree的工具(如
Ruby2Ruby) ,它会更加方便,后者使用s-expr并将其格式化为Ruby源代码。
铁Ruby
IronRuby通过生成MS IL代码以.NET平台为目标。
它利用DLR,该系统收集语言实现的常用功能,例如从表达式树生成MS IL等。
调试后端
DLR生成.NET MS IL,并且还可以生成MS IL调试信息,这意味着IronRuby可以同时使用.NET调试工具和Visual Studio调试器GUI。
图形用户界面
可以使用Visual Studio,但是Ruby的Steel IDE中的SapphireSteel Ruby(也基于Visual Studio)具有对IronRuby开发的支持。
调试功能应该在将来的版本中可用。
其余领域
本文展示了一些当前可用于Ruby的调试工具的示例,但并未声明其完整性。
IDE中还提供了其他GUI和后端,例如ActiveState的Komodo或对Ruby实现或调试功能提供不同级别支持的后端。
尽管未提供Ruby实现
XRuby ,但它具有
调试支持 。
也没有提到Ruby 1.9,尽管它已经正式发布,但它似乎仍在大量开发中。
由于Ruby 1.9的VM也使用字节码解释器,因此可能有类似于Rubinius的方案。
免责声明 :替代Ruby实现和调试支持的开发现在正在快速发展。
因此:将本文作为Ruby中调试支持的概述-在您阅读本文时,Ruby实现和工具的
实际调试支持可能已经改变和改进。
翻译自: https://www.infoq.com/articles/ruby-debuggers-survey/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1
ruby 调试