在线文档教程

2.调试器 | 2. Debugger

2调试器

2.1开始

要使用调试器,基本步骤如下:

第1步。通过调用启动调试器debugger:start()

Monitor window显示有关所有调试过程,解释模块和选定选项的信息。最初通常没有调试过程。首先,必须指定哪些模块将被调试(也称为解释)。按以下步骤进行:

步骤2.在Monitor窗口中选择Module> Interpret 。

Interpret Modules window显示。

第3步。从解释对话框窗口中选择适当的模块。

注意

只有用选项debug_info集编译的模块才能被解释。“解释模块”窗口中的括号内会显示不可解释的模块。

步骤4. 在Monitor窗口中,选择Module>要解释的模块> View。

源文件的内容显示在View Module window

第5步。设置breakpoints,如果有的话。

步骤6.启动要调试的程序。这是从 Erlang shell 正常完成的。

执行解释模块中的代码的所有进程都显示在监视器窗口中。

第7步。要附加到其中某个进程,请双击它,或者选择进程,然后选择进程>附加。附加到流程打开了Attach Process window这个过程。

第8步。从Attach Process窗口,您可以控制流程执行,检查变量值,设置断点等。

2.2 断点和断点对话窗口

一旦解释了适当的模块,就可以在源代码中的相关位置设置断点。断点是以行为基础指定的。当进程到达断点时,它停止并等待用户的命令(步骤跳过继续 ...)。

注意

当进程到达断点时,只有该进程停止。其他进程不受影响。

使用 Monitor 窗口,View Module 窗口或 Attach Process 窗口的 Break 菜单创建和删除断点。

可执行行

要产生效果,必须在可执行行设置断点,该行是包含可执行表达式(如匹配或函数调用)的代码行。在case语句或receive语句中包含注释,函数头或模式的空白行或行不可执行。

在以下示例中,第2,4,6,8和11行是可执行的行:

1: is_loaded(Module,Compiled) -> 2: case get_file(Module,Compiled) of 3: {ok,File} -> 4: case code:which(Module) of 5: ?TAG -> 6: {loaded,File}; 7: _ -> 8: unloaded 9: end; 10: false -> 11: false 12: end.

状态和触发器操作

断点可以是活性无活性。非活动断点被忽略。

每个断点都有一个触发器动作,用于指定进程到达(并停止)时发生的事情:

  • 启用 - 断点保持活动状态(默认)。

  • 禁用 - 断点将变为非活动状态。

  • 删除 - 断点将被删除

线路断点

线路断点在模块的某一行中创建。

图2.1:换行符对话窗口

右键单击模块条目打开一个弹出菜单,从中可以选择适当的模块

当模块显示在“查看模块”窗口或“附加处理”窗口中时,也可以通过双击该行来创建(并删除)断点。

条件断点

在模块中的某一行创建条件断点,但只有在指定的条件为真时才会停止到达断点的进程。

条件由用户指定为模块名称CModule和函数名称CFunction。当进程到达断点时,CModule:CFunction(Bindings)进行评估。当且仅当此函数调用返回时true,该过程停止。如果函数调用返回false,断点将被忽略。

Bindings是变量绑定的列表。要检索Variable(作为原子给出)的值,请使用函数int:get_binding(Variable,Bindings)。该函数返回unbound{value,Value}

图2.2:条件中断对话窗口

右键单击模块条目打开一个弹出菜单,从中可以选择适当的模块

例子:

c_test:c_break/1模块中的第6行添加了条件断点调用fact。每次到达断点时,都会调用该函数。当N等于3时,函数返回true并且过程停止。

提取自fact.erl*

5. fac(0) -> 1; 6. fac(N) when N > 0, is_integer(N) -> N * fac(N-1).

定义c_test:c_break/1*

-module(c_test). -export([c_break/1]). c_break(Bindings) -> case int:get_binding('N', Bindings) of {value, 3} -> true; _ -> false end.

功能断点

函数断点是一组行断点,一个位于指定函数的每个子句的第一行。

图2.3:功能中断对话窗口

要打开一个可从中选择适当模块的弹出式菜单,请右键单击模块条目。

要在列表框中显示模块的所有功能,请在指定模块名称时单击确定按钮(或按 Return Tab 键)。

2.3 堆栈跟踪

Erlang 仿真器跟踪堆栈跟踪,以及有关最近函数调用的信息。如果发生错误,则使用此信息,例如:

1> catch a+1. {'EXIT',{badarith,[{erlang,'+',[a,1],[]}, {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,573}]}, {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,357}]}, {shell,exprs,7,[{file,"shell.erl"},{line,674}]}, {shell,eval_exprs,7,[{file,"shell.erl"},{line,629}]}, {shell,eval_loop,3,[{file,"shell.erl"},{line,614}]}]}}

有关堆栈跟踪的详细信息,请参阅Errors and Error HandlingErlang参考手册中的一节。

调试器通过跟踪最近调用的解释函数来模拟堆栈跟踪。(真正的堆栈跟踪不能使用,因为它显示调试器的哪些功能已被调用,而不是哪些解释功能。)

这些信息可以用来遍历函数调用链,使用中的向上向下按钮Attach Process window

默认情况下,调试器仅保存有关递归函数调用的信息,即尚未返回值的函数调用(选项Stack On,No Tail)。

然而,有时候,保存所有的呼叫,甚至是尾递归调用都是有用的。这是通过Stack On,Tail选项完成的。注意,当有很多尾递归调用时,这个选项会消耗更多的内存并减慢解释函数的执行速度。

要关闭调试器堆栈跟踪工具,请选择选项堆栈关闭

注意

如果发生错误,在这种情况下,堆栈跟踪变为空。

有关如何更改堆栈跟踪选项的信息,请参见部分Monitor Window

2.4 监视器窗口

监视器窗口是调试器的主窗口,并显示以下内容:

  • 包含所有解释模块名称的列表框双击模块将打开“查看模块”窗口。

  • 选择哪些选项

  • 有关所有调试过程的信息,即所有在解释模块中已经或正在执行代码的过程

图2.4:监视窗口

自动连接盒,堆栈跟踪标签,返回跟踪大小的标签,字符串框中显示一些选项设置。有关这些选项的详细信息,请参见部分Options Menu

过程网格

PID

进程标识符。

初始呼叫

这个过程首先调用一个解释函数。(Module:Function/Arity

Name

注册名称,如果有的话。如果未显示注册名称,可能是调试器在注册名称之前收到有关该过程的信息。尝试选择编辑>刷新。

状态

目前的状态如下:

idle

解释函数调用已经返回一个值,并且该进程不再执行解释代码。

running

该过程正在运行。

waiting

这个过程正在一个receive声明中等待。

中断

该过程在断点处停止。

出口

该过程已终止。

no_conn

没有连接到进程所在的节点。

信息

更多信息,如果有的话。如果进程在断点处停止,则该字段包含有关该位置的信息{Module,Line}。如果进程已终止,则该字段包含退出原因。

文件菜单

载入设定...

尝试从之前使用保存设置保存的文件加载和恢复调试器设置(见下文)。任何错误都会被忽略。

请注意,由 Erlang / OTP R16B01 或更高版本保存的设置不能被 Erlang / OTP R16B 或更早版本读取。

保存设置

将调试器设置保存到文件。这些设置包括一组解释文件,断点和所选选项。这些设置可以在以后的调试器会话中使用 Load Settings (见上文)恢复。任何错误都会被忽略。

Exit

停止调试器。

编辑菜单

Refresh

更新关于调试过程的信息。有关所有已终止进程的信息将从窗口中删除。关闭已终止进程的所有附加进程窗口。

Kill All

使用终止窗口中列出的所有进程exit(Pid,kill)

模块菜单

解读

打开Interpret Modules window,可以指定要解释的新模块。

删除所有

停止解释所有模块。在解释模块中执行的进程终止。

对于每个解释的模块,相应的条目将添加到模块菜单中,并带有以下子菜单:

删除

停止解释所选模块。在此模块中执行的进程终止。

View

打开一个View Module window,显示所选模块的内容。

处理菜单

以下菜单项适用于当前选定的进程,前提是它在断点处停止(有关详细信息,请参见部分Attach Process window):

StepNextContinueFinish

以下菜单项适用于当前选定的进程:

Attach

附加到过程并打开一个Attach Process window

Kill

终止使用过程exit(Pid,kill)

中断菜单

此菜单中的项目用于创建和删除断点。有关详情,请参阅部分Breakpoints

越线

设置一个线断点。

有条件的休息

设置一个条件断点。

功能中断

设置功能断点。

全部启用

启用所有断点。

禁用所有

禁用所有断点。

删除所有

删除所有断点。

对于每个断点,将相应的条目添加到Break菜单,从中可以禁用,启用或删除断点并更改其触发器操作。

选项菜单

跟踪窗口

将区域设置为在Attach Process window。中可见。不影响现有的附加过程窗口。

自动连接

设置调试过程自动附加的事件。影响现有的调试过程。

  • 第一次调用 - 一个进程首次调用解释模块中的函数。

  • 退出时 - 进程终止时。

  • 中断 - 当一个进程到达一个断点时。

堆栈跟踪

设置堆栈跟踪选项,请参见部分Stack Trace。不影响现有的调试过程。

  • 堆叠,尾巴 - 保存关于当前所有呼叫的信息。

  • Stack On,No Tail - 保存关于当前呼叫的信息,当进行尾递归调用时丢弃先前的信息。

  • 堆叠关闭 - 不保存关于当前通话的任何信息。

字符串

设置要作为字符串打印的整数列表。不影响现有的调试过程。

  • + PC标志的使用范围 -使用由设定的可打印字符范围erl(1)标志+pc。返回跟踪大小...设置从附加处理窗口检查调用堆栈时要获取多少个调用帧。不影响现有的附加过程窗口.Windows Menu为每个打开的调试器窗口包含一个菜单项。选择其中一个项目会产生相应的窗口。帮助菜单帮助显示调试器文档。此功能需要Web浏览器。2.5解释模块窗口解释模块窗口用于选择要解释的模块。最初,该窗口显示erl当前工作目录的模块(文件)和子目录。可解释模块是为其.beam使用选项debug_info集编译的文件与源代码位于同一目录中,或位于其ebin旁边的目录中。未满足这些要求的模块不可解释,因此显示在括号内。选项debug_info会导致调试信息或摘要代码被添加到.beam文件中。这增加了文件大小,并可以重建源代码。因此,建议不要将调试信息包含在针对目标系统的代码中。例如,如何使用调试信息编译代码erlc:%erlc + debug_info module.erl一个如何用Erlang外壳的调试信息编译代码的例子:4> c(module,debug_info)。图2.5:解释模块窗口要浏览文件层次并解释合适的模块,可以选择模块名称并单击选择(或按回车键),或者双击模块名称。解释模块具有类型erl src。要解释所选目录中的所有显示模块,请单击全部。要关闭该窗口,请单击完成。注意当调试器以全局模式启动时(默认情况下,请参阅debugger:start/0),在所有已知的Erlang节点上添加(或删除)用于解释的模块(或删除)。2.6附加过程窗口从附加过程窗口,您可以与调试过程进行交互。为每个已连接的进程打开一个窗口。请注意,附加到进程时,其执行会自动停止。图2.6:附加进程窗口窗口分为以下五部分:

  • 代码区域,显示正在执行的代码。代码是缩进的,每一行都以其行号作为前缀。如果进程执行停止,当前行将被标记为-->.在行处的现有断点用停止符号标记。在插图中显示的示例中,执行在第6行停止,然后执行fac/1...

活动断点以红色显示,非活动断点以蓝色显示。

  • 按钮区域,其中有按钮,用于快速访问加工过程菜单。

  • 如果进程执行停止,则可以在已调试进程的上下文中对函数进行评估。

  • 绑定区域,显示所有变量绑定。如果单击变量名,则该值将显示在计算程序区域中。双击一个变量名,打开一个窗口,在其中可以编辑变量值.。但是,请注意,PID、端口、引用或乐趣值不能被编辑,除非它们可以在运行的系统中表示。

  • 跟踪区域,它显示进程的跟踪输出。

++ (N) <L>函数调用,其中N是调用级别和L行号。-- (N) 函数返回值

==> Pid : Msg该消息Msg被发送到进程Pid。<== Msg该消息Msg已收到。++ (N) receive在等待中receive。++ (N) receive with timeout在等待中receive...after。Trace区域还显示Back Trace,堆栈上当前函数调用的摘要。

使用选项菜单,您可以设置要显示的区域。默认情况下,将显示除跟踪区域之外的所有区域。

文件菜单

密闭

关闭此窗口并脱离进程。

编辑菜单

排队..。

转到指定的行号。

搜索...

搜索指定的字符串。

过程菜单

Step

执行当前的代码行,进入任何(解释的)函数调用。

下一个

执行当前的代码行并停在下一行。

继续

继续执行。

Finish

继续执行,直到当前函数返回。

跳跃

跳过当前代码行并停在下一行。如果用在函数体的最后一行,则函数返回skipped

时间到

执行receive...after语句时模拟超时。

停止

停止正在运行的进程的执行,也就是使进程在断点处停止。该命令在下次进程收到消息时生效(明显)。

Where

验证执行的当前位置在代码区域中是否可见。

Kill

终止使用过程exit(Pid,kill)

消息

检查进程的消息队列。该队列显示在评估程序区域中。

返回跟踪

在“跟踪”区域中显示进程的反向跟踪,堆栈上当前函数调用的摘要。要求Trace区域可见并且Stack Trace选项为Stack On,TailStack On,No Tail

向上

检查堆栈上的前一个函数调用,显示位置和变量绑定。

检查堆栈上的下一个函数调用,显示位置和变量绑定。

选项菜单

跟踪窗口

设置哪些区域是可见的。不影响其他附加处理窗口。

堆栈跟踪

与在中相同Monitor window,但仅影响窗口所连接的调试过程。

字符串

与在中相同Monitor window,但仅影响窗口所连接的调试过程。

返回跟踪大小

设置在检查调用堆栈时将获取多少调用帧。不影响其他附加进程窗口。

“中断”、“窗口”和“帮助”菜单

中断视窗帮助菜单是一样的Monitor Window,只是休息菜单只适用于本地断点。

2.7 查看模块窗口

查看模块窗口显示解释模块的内容,并可以设置断点。

图2.7:查看模块窗口

源代码是缩进的,每行都以其行号作为前缀。

点击一行突出显示它并选择它是可以从断点功能目标菜单。要在一条线上设置线断点,请双击它。要删除断点,请双击带有现有断点的行。

断点标有停止符号。

文件和编辑菜单

文件”和“ 编辑”菜单与“ 文件”菜单中的相同Attach Process Window

“中断”、“窗口”和“帮助”菜单

休息视窗帮助菜单是一样的Monitor Window,不同之处在于打破菜单只适用于本地断点。

2.8性能

解释代码的执行速度自然慢于定期编译的模块。使用调试器还会增加系统中的进程数量,因为每个调试进程都会创建另一个进程(元进程)。

同样值得一提的是,调试时带定时器的程序可能会有不同的表现。停止执行进程时(例如,在断点处),尤其如此。然后在其他进程中发生超时,这些进程可以像平常一样继续执行。

2.9码加载机构

代码加载的工作方式与往常一样,只是解释的模块也存储在数据库中,而调试的进程只使用此存储的代码。重新解释解释模块也会导致新版本被存储,但不会影响执行旧版本代码的现有进程。这意味着Erlang的代码替换机制不适用于调试的进程。

2.10调试远程节点

通过使用debugger:start/1,您可以指定调试器是以本地还是全局模式启动:

debugger:start(local | global)

如果没有提供参数,调试器以全局模式启动。

在本地模式下,代码仅在当前节点解释。在全局模式下,代码在所有已知节点处被解释。执行解释代码的其他节点上的进程会自动显示在“监视器”窗口中,并可像其他任何调试过程一样附加进程。

可能但肯定不推荐在网络中的多个节点上以全局模式启动调试器,因为节点互相干扰,导致行为不一致。