添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Sun Studio 12:使用 dbx 调试程序

第 1 章 dbx 入门

dbx 是一个交互式源码级命令行调试工具。可以使用它来以可控方式运行程序以及检查已停止程序的状态。使用 dbx 可以完全控制程序的动态执行过程,包括收集性能和内存使用数据、监视内存访问及检测内存泄漏。

可以使用 dbx 调试采用 C、C++ 或 Fortran 编写的应用程序。也可以调试使用 Java TM 代码和 C JNI(Java Native Interface,Java 本地接口)代码或 C++ JNI 代码混合编写的应用程序,但存在一些限制(请参见 使用 dbx 调试 Java 代码的限制 )。

本章提供使用 dbx 调试应用程序的基本知识。其中包含以下各节:

编译调试代码

编译调试代码

在使用 dbx 对程序进行源代码级调试前,必须使用 -g 选项(C 编译器、C++ 编译器、Fortran 95 编译器和 Java 编译器均接受此选项)编译程序。有关更多信息,请参见 编译调试程序

启动 dbx 和装入程序

要启动 dbx ,请在 shell 提示符下键入 dbx 命令:

Attached to process 1855 stopped in _libc_poll at 0xfef9437c 0xfef9437c: _libc_poll+0x0004: ta 0x8 Current function is main 48 XtAppMainLoop(app_context); (dbx)

有关 dbx 命令和启动选项的更多信息,请参见 dbx 命令 dbx (1) 手册页,或键入 dbx -h

如果 dbx 已在运行,可使用 debug 命令装入要调试的程序,或从正在调试的程序切换到其他程序:

运行包含 Java 代码的应用程序时,运行参数传递给 Java 应用程序而不是 JVM 软件。请勿将主类名作为参数。

如果重复执行 run 命令时没有使用参数, 程序重新启动时使用上一个 run 命令中的参数或重定向。可以使用 rerun 命令重置选项。有关 run 命令的更多信息,请参见 run 命令 。有关 rerun 命令的更多信息,请参见 rerun 命令

应用程序可能会运行完毕或正常终止。如果设置了断点,程序可能会在断点处停止。如果应用程序中有错误,会因内存故障或段故障而停止。

使用 dbx 调试程序

可能出于下列原因之一调试程序:

为了确定程序在何处以及为何导致崩溃。确定崩溃原因的方法包括:

检查核心转储文件

确定程序发生崩溃的位置,可能需要检查核心转储文件,即程序崩溃时的程序内存映像。可使用 where 命令(请参见 where 命令 )确定程序在转储核心时的执行位置。

dbx 无法像对待本地代码那样通过核心转储文件来指明 Java 应用程序的状态。

要调试 核心转储文件,请键入:

Reading libdl.so.1 Reading libc_psr.so.1 program terminated by signal SEGV (no mapping at the fault address) Current function is main 9 printf("string ’%s’ is %d characters long\n", msg, strlen(msg)); (dbx) where [1] strlen(0x0, 0x0, 0xff337d24, 0x7efefeff, 0x81010100, 0xff0000), at 0xff2b6dec =>[2] main(argc = 1, argv = 0xffbef39c), line 9 in "foo.c" (dbx)

有关调试核心转储文件的更多信息,请参见 调试核心转储文件 。有关使用调用栈的更多信息,请参见 查看调用栈


注 –

如果程序与共享库动态链接,最好在创建核心转储文件的操作环境中调试该文件。有关如何调试在不同的操作环境中创建的核心转储文件的信息,请参见 调试不匹配的核心转储文件

断点是程序中要暂时停止程序的执行并让 dbx 进行控制的位置。在程序内怀疑存在错误之处设置断点。如果程序崩溃,请确定崩溃的发生位置,然后在这部分代码前设置断点。

程序在断点处停止时,便可以检查程序的状态和变量值。使用 dbx 可以设置多种类型的断点(请参见 使用 Ctrl+C 停止进程 )。

最简单的断点类型就是停止断点。可以设置用于 在函数或过程中停止的停止断点。例如,要在调用 main 函数时停止:

单步执行程序

程序在断点处停止后, 可能希望按一次执行一个源代码行的方式执行程序,在此时比较程序的实际状态与预期状态。可以使用 step next 命令来执行此操作。这两个命令都是执行程序的一个源代码行,当执行完相应行时即停止。但在处理包含函数调用的源代码行时有所差别: step 命令步入函数,而 next 命令步过函数。

step up 命令会一直执行,直至当前函数将控制权返回给调用它的函数为止。

step to 命令会尝试步入当前源代码行中的指定函数;如果未指定任何函数,则尝试步入由当前源代码行的汇编代码确定调用的最后一个函数。

某些函数(特别是 printf 之类的库函数)可能未使用 -g 选项编译,因此 dbx 无法步入这些函数。在这种情况下, step next 执行功能相似。

以下示例说明如何使用 step next 命令以及在 设置断点 中设置的断点。

查看调用栈

调用栈表示那些已调用但尚未返回至各自调用方的所有当前活动例程。在该栈中,函数及其参数按其调用顺序存放。栈跟踪显示程序流中执行停止位置及执行到达此点的过程。它提供了有关程序状态的最简明的描述。

要显示栈跟踪,请使用 where 命令:

(dbx) where [1] printf(0x10938, 0x20a84, 0x0, 0x0, 0x0, 0x0), at 0xef763418 =>[2] printit(msg = 0x20a84 "hello world\n"), line 6 in "t.c" [3] main(argc = 1, argv = 0xefffe93c), line 13 in "t.c" (dbx)

对于使用 -g 选项编译的函数,参数名及其类型是已知的,因此会显示精确的值。对于无调试信息的函数,显示的参数值是十六进制数。这些数字未必都有意义。例如,在上述栈跟踪中,帧 1 所示为 SPARC 输入寄存器 $i0 $i5 的内容,但仅寄存器 $i0 $i1 的内容有意义,因为只有两个参数传递到 单步执行程序 所示的示例中的 printf

可以在未使用 -g 选项编译的函数中停止。在此类函数中停止时, dbx 在栈内向下搜索其函数是使用 -g 选项编译的第一帧(本例中为 printit() ),并为其设置当前范围(请参见 程序作用域 )。这用箭头符号 ( => ) 表示。

有关调用栈的更多信息,请参见 效率方面的考虑

虽然栈跟踪可能包含足够的信息,可以完全表明程序的状态,但仍可能需要查看更多 变量的值。 print 命令可以求表达式的值,并根据表达式的类型打印值。以下示例中例举了几个简单的 C 表达式:

查找内存访问问题和内存泄漏

运行时检查由两部分组成:内存访问检查及内存使用和泄露检查。访问检查将检查被调试应用程序是否不当使用了内存。内存使用和泄露检查包括跟踪所有仍存在的堆空间,然后在需要时或程序终止时,扫描可用数据空间以及识别无引用的空间。


注 –

只能在 Solaris 平台上进行运行时检查。

可以使用 check 命令启用内存访问检查及内存使用和泄露检查。要仅 启用 内存访问检查,请键入:

启用所需的运行时检查类型后,运行程序。程序正常运行,但速度很慢,因为每次进行内存访问前都要检查其有效性。如果 dbx 检测到访问无效,便会显示错误的类型和位置。此时,可以使用 dbx 命令(如 where 命令)获取当前栈跟踪,也可以使用 print 命令检查变量。


注 –

不能对使用 Java 代码和 C JNI 代码或 C++ JNI 代码混编的应用程序使用运行时检查。

有关使用运行时检查的详细信息,请参见 第 9 章,使用运行时检查

退出 dbx dbx 会话是从启动 dbx 之时一直持续到 退出 dbx ;在 dbx 会话期间,可以连续调试任意数量的程序。

要退出 dbx 会话,请在 dbx 提示符下键入 quit

如果启动 dbx 时使用 process_id 选项将其连接到正在运行的进程,退出调试会话,该进程仍存在并继续运行。 dbx 在退出会话之前执行隐式 detach

有关退出 dbx 的更多信息,请参见 退出调试 .。

访问 dbx 联机帮助

dbx 包含一个帮助文件,可使用 help 命令进行访问: