用于运行、单步执行和继续进行的命令(run、rerun、 next、step 和 cont )称为进程控制命令。与cont at 命令中描述的事件管理命令一起使用,当程序在 dbx 下执行时,可以控制程序的运行时行为。
本章由以下部分组成:
首次将程序装入 dbx 时,dbx 会导航到程序的 "main" 块(对 C、C++ 和 Fortran 90 而言是 main;对 Fortran 77 而言是 MAIN;对 Java 代码而言是 main 类)。dbx 会等待您发出进一步的命令;您可以在代码中导航或使用事件管理命令。
运行程序之前,可以在程序内设置断点。
调试使用 JavaTM 代码和 C JNI(Java Native Interface,Java 本地接口)代码或 C++ JNI 代码混合编写的应用程序时,可能需要在尚未装入的代码中设置断点。有关在此类代码中设置断点的信息,请参见在本地 (JNI) 代码中设置断点。
(dbx) run |
可以选择添加命令行参数和输入、输出重定向。
(dbx) run [arguments][ < input_file] [ > output_file] |
无法重定向 Java 应用程序的输入和输出。
run 命令的输出将覆盖现有文件,即使已为正在运行 dbx 的 shell 设置了 noclobber。
不带参数的 run 命令将使用上次的参数和重定向来重新启动程序。有关更多信息,请参见run 命令。rerun 命令重新启动程序并清除原始参数和重定向。有关更多信息,请参见rerun 命令。
可能需要调试已经运行的程序。如果属于下列情况,便需要连接正在运行的进程:
要调试正在运行的服务器,但又不想停止或中止服务器。
要调试正在运行的具有图形用户界面的程序,但又不想重新启动该程序。
程序处于无限循环,要调试该程序但又不想将其中止。
通过将程序的 process_id 编号用作 dbx debug 命令的一个参数,可以将 dbx 连接到正在运行的程序。
程序调试完毕后,便可以使用 detach 命令来解除 dbx 对程序的控制,而无需终止进程。
如果在将 dbx 连接到正在运行的进程后退出 dbx,dbx 会在终止前隐式分离。
要将 dbx 连接到独立于 dbx 运行的程序,可以使用 attach 命令或 debug 命令。
要将 dbx 连接到已经运行的进程,请键入:
(dbx) debug program_name process_id |
或
(dbx) attach process_id |
可以用一个 –(破折号)代替 program_name;dbx 将自动查找与进程 ID 相关联的程序并将其载入。
% dbx program_name process_id |
dbx 连接到程序后,程序便停止执行。将其他程序装入 dbx 时,可以检查该程序。可以使用任何事件管理或进程控制命令来调试该程序。
如果在调试现有进程时将 dbx 连接到一个新进程,会出现下列情况:
如果使用 run 命令启动当前正在调试的进程,那么 dbx 会在连接新进程之前终止此进程。
如果使用 attach 命令或通过在命令行中指定进程 ID 来开始调试当前进程,那么 dbx 会在连接新进程之前从当前进程中分离。
如果要将 dbx 连接到的进程由于 SIGSTOP 信号、SIGTSTOP 信号、SIGTTIN 信号或 SIGTTOUT 信号而停止,则连接会成功,并显示类似以下的消息:
dbx76: warning: Process is stopped due to signal SIGSTOP
该进程是可检查的,但是要恢复它,您需要使用 cont 命令向其发送 SIGCONT 信号:
(dbx) cont -sig cont |
可以对具有某些异常的连接的进程使用运行时检查。请参见对连接的进程使用运行时检查。
程序调试完毕后,请使用 detach 命令从程序中分离 dbx。这时程序将恢复独立于 dbx 而运行,除非在分离时指定 -stop 选项。
(dbx) detach |
在临时应用其他基于 /proc 的调试工具而这些工具可能由于 dbx 有专用访问而被阻止时,可以分离进程并将其保留在停止状态。例如:
(dbx) oproc=$proc # Remember the old process ID (dbx) detach -stop (dbx) /usr/proc/bin/pwdx $oproc (dbx) attach $oproc |
有关更多信息,请参见detach 命令。
dbx 支持两个基本单步执行命令:next 和 step,外加 step 命令的两个变体(称为 step up 和 step to)。next 和 step 这两个命令均使程序于再次停止前执行一个源代码行。
如果执行的行中包含函数调用,next 命令允许执行调用并于下一行停止(“步过”调用)。step 命令停止在被调用函数的第一行(“步入”调用)。
step up 命令会在步入函数之后,将程序返回到调用方函数。
step to 命令会尝试步入当前源代码行中的指定函数;如果未指定任何函数,则尝试步入由当前源代码行的汇编代码确定调用的最后一个函数。可能会因为条件转移或当前源代码行内没有被调用的函数,而无法执行函数调用。在这些情况下,step to 命令将步过当前源代码行。
有关 next 和 step 命令的更多信息,请参见next 命令和step 命令。
要单步执行指定行数的代码,请使用 dbx 的 next 或 step 命令,并在命令后跟要执行代码的行数 [n]。
(dbx) next n |
或
(dbx) step n |
step_granularity 环境变量确定 step 命令和 next 命令单步执行代码的单元(请参见设置 dbx 环境变量)。其单元可以是语句或行。
step_events 环境变量控制步骤中是否启用断点(请参见设置 dbx 环境变量)。
step_abflow 环境变量控制当 dbx 检测到将发生不寻常的控制流更改时,是否停止运行(请参见设置 dbx 环境变量)。对 siglongjmp() 或 longjmp() 的调用或异常抛出有可能导致此类控制流更改。
要步入从当前源代码行调用的函数,请使用 step to 命令。例如,要步入函数 GetDiscount()(),请键入:
step to GetDiscount |
要步入最后调用的函数,请键入:
step to |
(dbx) cont |
cont 命令有一个变体 (cont at line_number),它允许指定恢复程序执行的当前程序位置行之外的行。这样可以跳过已知引起问题的一行或多行代码,而无需重新编译。
(dbx) cont at 124 |
行号是相对于程序停止的文件求出的;给定的行号必须位于当前函数的作用域内。
将 cont at line_number 命令和 assign 命令配合使用,可以避免执行包含某个函数调用(可能会错误地计算某一变量的值)的代码行。
使用 cont at line_number 来跳过包含不正确地计算值之函数调用的行。
假定程序停止于第 123 行。第 123 行调用函数 how_fast(),该函数将不正确地计算变量 speed。您知道 speed 变量应该取什么值,因此便为 speed 赋值。然后跳过对 how_fast() 的调用,于第 124 行处继续执行程序。
(dbx) assign speed = 180; cont at 124; |
有关更多信息,请参见cont 命令。
如果使用带有 when 断点命令的 cont 命令,则程序每次尝试执行第 123 行时,都会跳过对 how_fast() 的调用。
(dbx) when at 123 { assign speed = 180; cont at 124;} |
有关 when 命令的更多信息,请参见:
程序被停止时,可以使用 dbx call 命令调用函数,以此接受必须传递给被调用函数的参数值。
(dbx) call change_glyph(1,3) |
如果参数是可选项,则必须在 function_name 后键入括号。例如:
(dbx) call type_vehicle() |
可以使用 call 命令显式调用函数;或通过求包含函数调用的表达式的值或使用 stop in glyph -if animate() 之类的条件修饰符来隐式调用函数。
C++ 虚拟函数与其他函数一样,可以使用 print 命令或 call 命令(请参print 命令或call 命令)或任何其他执行函数调用的命令进行调用。
如果定义函数的源文件已使用 –g 选项编译,或原型声明在当前作用域可见,dbx 会检查参数的个数和类型,如果存在不匹配便发出错误消息。否则, dbx 不会检查参数的个数并继续执行调用。
缺省情况下,在每个 call 命令之后,dbx 都会自动调用 fflush(stdout) 来确保 I/O 缓冲区内存储的所有信息全部被打印。要关闭自动刷新,请将 dbx 环境变量 output_auto_flush 设置为 off。
对 C++ 而言,dbx 可处理隐式 this 指针、缺省参数和函数重载。如有可能,C++ 重载函数将自动求解。如果存在任何二义性(例如,未使用 -g 编译函数),dbx 将显示重载名称列表。
使用 call 命令时,dbx 的行为就好像您使用了 next 命令一样(从被调用的函数返回)。但是,如果程序在被调用的函数内遇到断点,dbx 将在断点处停止程序并发出消息。如果现在键入 where 命令,栈跟踪将显示调用源自 dbx 命令级。
如果继续执行,调用会正常返回。如果尝试中止、运行、重新运行或调试,当 dbx 试图从嵌套中恢复时,命令便会终止。然后,可以重新发出命令。另外,可以使用 pop -c 命令弹出最近调用之前的所有帧。
通过使用 call 命令或通过打印包含调用的表达式来在要调试的进程中进行调用时,可能会导致不明显的严重中断。以下是一些要密切注意的情况以及摆脱这些情况的方法。
调用可能会陷入无限循环(您可以中断该循环),或导致段故障。在许多情况下,您可以使用 pop -c 命令返回到调用方。
在多线程应用程序中进行调用时,将会恢复所有线程以避免死锁,所以您可能会在进行调用的线程之外的其他线程上看到负面影响。
断点条件中使用的调用可能会搞乱事件管理(请参见恢复执行)。
dbx 进行的一些调用会“安全地”执行。如果遇到问题(一般是段故障)而非通常的 "Stopped with call to ...",则 dbx 会:
忽略任何 stop 命令(包括那些因检测内存访问错误而使用的命令)
自动发出 pop -c 命令以返回到调用方
继续执行
对于下面的调用,dbx 所使用的是安全调用:
由 display 命令打印的表达式中发生的调用。失败的调用显示为: ic0->get _data() = <call failed>
要诊断此类故障,请尝试使用 print 命令打印表达式。
对 db_pretty_print()() 函数的调用,但使用 print -p 命令时除外。
事件条件表达式中使用的调用。包含失败调用的条件会计算为 false。
执行 pop 命令期间为调用析构函数所做的调用。
所有内部调用。
可以通过按 Ctrl+C (^C) 来停止 dbx 中正在运行的进程。使用 ^C 停止进程时,dbx 会忽略 ^C,但子进程会将其作为 SIGINT 予以接受并停止。然后,便可以检查进程,就像进程是通过断点被停止的一样。
若要在使用 ^C 停止程序后恢复执行,请使用 cont 命令。要恢复执行时,不需要使用 cont 可选修饰符 sig signal_name。取消待决信号之后,cont 命令将恢复子进程。