Sun Studio 12 Update 1:使用 dbx 调试程序

第 8 章 求值和显示数据

dbx 中,可以执行两种类型的数据检查:

本章由以下部分组成:

求变量和表达式的值

本节讨论如何使用 dbx 对变量和表达式求值。

验证 dbx 使用的变量

如果不确定 dbx 对其求值的变量,可使用 which 命令查看 dbx 使用的全限定名。

要查看在其中定义变量名的其他函数和文件,请使用 whereis 命令。

有关这些命令的信息,请参见which 命令whereis 命令

当前函数作用域之外的变量

要对当前函数的作用域之外的变量进行求值或监视时,请执行下列操作之一:

打印变量、表达式或标识符的值

表达式应遵循当前语言的语法,但 dbx 中引入以用来处理作用域和数组的元语法除外。

要对本地代码中的变量或表达式求值,请键入:


print expression

可以使用 print 命令对 Java 代码中的表达式、局部变量或参数求值。

有关更多信息,请参见print 命令


注 –

dbx 支持 C++ dynamic_casttypeid 操作符。使用这两个操作符求表达式的值时, dbx 会调用由编译器提供的一些 rtti 函数。如果源代码没有明确使用这些操作符,编译器便不会生成这些函数,因此 dbx 将无法求表达式的值。


打印 C++ 指针

在 C++ 中,对象指针有两种类型:静态类型(在源代码中定义)和动态类型(对象进行类型转换之前的状况)。dbx 有时可以提供有关对象的动态类型的信息。

通常情况下,如果对象有虚拟函数表(即 vtable),dbx 便可使用 vtable 中的信息正确地确定对象的类型。

可以在 print 命令、display 命令或 watch 命令中使用 -r(递归)选项。此时 dbx显示通过类直接定义的所有数据成员以及从基类继承的所有数据成员。

在这些命令中还可使用 -d+d 选项,用来切换 dbx 环境变量 output_derived_type 的缺省行为。

如果在没有运行进程时使用 -d 标志或将 dbx 环境变量 output_dynamic_type 设置为 on,将生成 "program is not active" 错误消息,因为在调试核心转储文件时没有进程便无法访问动态信息。如果尝试通过虚拟继承来查找动态类型,将生成 "illegal cast on class pointers" 的错误消息。(在 C++ 中,从虚拟基类转换到派生类是非法的。)

对 C++ 程序中未命名参数求值

C++ 允许使用未命名的参数来定义函数。例如:


void tester(int)
{
};
main(int, char **)
{
   tester(1);
};

虽然未命名参数不能在程序中的其他地方使用,但是编译器会按某种格式对未命名参数进行编码,让您可以对其求值。该格式如下(这里,编译器为 %n 赋整数值):


_ARG%n

获取由编译器分配的函数名称,请键入 whatis 命令,并用函数名称作为其目标。


(dbx) whatis tester
void tester(int _ARG1);
(dbx) whatis main
int main(int _ARG1, char **_ARG2);

有关更多信息,请参见whatis 命令

对未命名的函数参数求值(或显示未命名的函数参数),请键入:


(dbx) print _ARG1
_ARG1 = 4

非关联化指针

非关联化指针时,请查看该指针指向的容器的内容。

非关联化指针时,dbx 会在命令窗格中显示求值;在下面的示例中,即由 t 指向的值:


(dbx) print *t
*t = {
a = 4
}

监视表达式

监视每次程序停止时表达式的值是一种了解特定表达式或变量的变化情况和变化时间的有效方法。display 命令可指示 dbx 监视一个或多个指定的表达式或变量。监视会一直持续进行,直至使用 undisplay 命令将其关闭为止。watch 命令用于在每个停止点处以相应点的当前作用域对表达式求值并进行打印。

要在每次程序停止时显示变量或表达式的值,请键入:


display expression, ...

一次可以监视不止一个变量。如果 display 命令不带选项,则将打印显示的所有表达式的列表。

有关更多信息,请参见display 命令

要监视每个停止点处表达式 expression 的值,请键入:


watch expression, ...

有关更多信息,请参见watch 命令

关闭显示(取消显示)

dbx 会一直显示监视的变量值,直至使用 undisplay 命令关闭显示为止。可以关闭指定的表达式的显示,也可以关闭当前监视的所有表达式的显示。

要关闭特定变量或表达式的显示,请键入:


undisplay expression

要关闭当前监视的所有变量的显示,请键入:


undisplay 0

有关更多信息,请参见undisplay 命令

为变量赋值

要为变量赋值,请键入:


assign variable = expression

对数组求值

对数组求值的方法与对其他类型变量求值的方法相同。

以下是 Fortran 数组示例:


integer*4 arr(1:6, 4:7)

要对数组求值,可使用 print 命令。例如:


(dbx) print arr(2,4)

使用 dbx print 命令可以对大型数组的一部分求值。数组求值包括:

进行数组分片时,可以使用跨距,也可以不使用跨距。(缺省跨距值为 1,即表示打印每个元素。)

数组分片

C、C++ 和 Fortran 语言中的 printdisplaywatch 命令支持数组分片。

C 和 C++ 的数组分片语法

对于数组的每个维度,对数组分片的完整 print 命令语法如下:


print array-expression [first-expression .. last-expression : stride-expression]

其中:

array-expression

求值结果应为数组或指针类型的表达式。

first-expression

要打印的第一个元素。缺省值为 0。

last-expression

要打印的最后一个元素。缺省值为数组上界。

stride-expression

跨距长度(跳过的元素个数为 stride-expression-1)。缺省值为 1。

第一个表达式、最后一个表达式和跨距表达式都是可选表达式,它们的求值结果应为整数。

例如:


(dbx) print arr[2..4]
arr[2..4] =
[2] = 2
[3] = 3
[4] = 4
(dbx) print arr[..2]
arr[0..2] =
[0] = 0
[1] = 1
[2] = 2

(dbx) print arr[2..6:2]
arr[2..6:2] =
[2] = 2
[4] = 4
[6] = 6

Fortran 数组分片语法

对于数组的每个维度, 对数组分片的完整 print 命令语法如下:


print array-expression [first-expression : last-expression : stride-expression]

其中:

array-expression

求值结果应为数组类型的表达式。

first-expression

某个范围内的第一个元素,也是要打印的第一个元素。缺省值为数组下界。

last-expression

某个范围内的最后一个元素,但如果跨距不等于 1,则可能不是要打印的最后一个元素。缺省值为数组上界。

stride-expression

跨距长度。缺省值为 1。

第一个表达式、最后一个表达式和跨距表达式都是可选表达式,它们的求值结果应为整数。对于 n 维数组片,请用逗号分隔各片的定义。

例如:


(dbx) print arr(2:6)
arr(2:6) =
(2) 2
(3) 3
(4) 4
(5) 5
(6) 6

(dbx) print arr(2:6:2)
arr(2:6:2) =
(2) 2
(4) 4
(6) 6

要指定行和列,请键入:


demo% f95 -g -silent ShoSli.f
demo% dbx a.out
Reading symbolic information for a.out
(dbx) list 1,12
    1         INTEGER*4 a(3,4), col, row
    2         DO row = 1,3
    3             DO col = 1,4
    4               a(row,col) = (row*10) + col
    5             END DO
    6         END DO
    7         DO row = 1, 3
    8                WRITE(*,’(4I3)’) (a(row,col),col=1,4)
    9        END DO
    10        END
(dbx) stop at 7
(1) stop at "ShoSli.f":7
(dbx) run
Running: a.out
stopped in MAIN at line 7 in file "ShoSli.f"
    7          DO row = 1, 3

要打印第 3 行,请键入:


(dbx) print a(3:3,1:4)
’ShoSli’MAIN’a(3:3, 1:4) =
        (3,1)   31
        (3,2)   32
        (3,3)   33
        (3,4)   34
(dbx)

要打印第 4 列,请键入:


(dbx) print a(1:3,4:4)
’ShoSli’MAIN’a(1:3, 1:4) =
        (1,4)   14
        (2,4)   24
        (3,4)   34
(dbx)

使用分片

以下是一个二维矩形 C++ 数组片示例(省略了缺省跨距 1)。


print arr(201:203, 101:105)

此命令打印大型数组的一部分元素。请注意,该命令省略了 stride-expression,使用的是缺省跨距值 1。

数组图,第 100 列至第 106 列和第 200 行至第 205 行。第 201 行至第 203 行的第 101 列至第 105 列中的元素带有阴影。

如上所示,前两个表达式 (201:203) 指定该二维数组的第一个维度中的数组片(三行一列)。数组片从第 201 行开始,到第 203 行结束。第二组表达式(以逗号与第一组表达式分开)用于定义第二个维度的数组片。该数组片从第 101 列开始,到第 105 列结束。

使用跨距

指示 print 跨越数组片时,dbx 只对该数组片中的某些元素求值,而跳过对其求值的各个元素之间一定数量的元素。

数组分片语法中的第三个表达式 stride-expression 指定跨距长度。stride-expression 值指定要打印的元素。缺省跨距值为 1,即: 对指定数组片中的所有元素求值。

以下数组与上一数组片示例使用的数组相同。这一次,print 命令中,第二个维度中数组片的跨距为 2。


print arr(201:203, 101:105:2)

如图所示,使用跨距 2 时,将打印所有第二个元素,而跳过所有其他元素。

数组图,第 100 列至第 106 列和第 200 行至第 205 行。第 201 行至第 203 行的第 101 列、第 103 列和第 105 列中的元素带有阴影。

对于省略的表达式,打印时取与数组的声明大小相等的缺省值。以下是如何使用简化语法的示例。

对于一维数组,请使用下列命令:

print arr

使用缺省边界打印整个数组。

print arr(:)

使用缺省边界和缺省跨距 1 打印整个数组。

print arr(::stride-expression)

使用跨距 stride-expression 打印整个数组。

对于二维数组,可使用以下命令打印整个数组。


print arr

要打印二维数组中第二个维度的所有第三个元素,请键入:


print arr (:,::3)

使用美化打印

美化打印让程序可通过函数调用以自己的方式呈现表达式值。如果在 print 命令、rprint 命令、 display 命令或 watch 命令中指定 -p 选项,则 dbx 会搜索格式为 const chars *db_pretty_print(const T *, int flags, const char *fmt) 的函数并调用它,从而替换返回值以便打印或显示。

以该函数的 flags 参数传递的值是按位操作值或以下所列之一:

FVERBOSE

0x1

目前尚未实现,始终设置 

FDYNAMIC

0x2

-d

FRECURSE

0x4

-r

FFORMAT

0x8

-f (如果设置,fmt 是格式部分)

FLITERAL

0x10

-l

db_pretty_print() 函数可以是静态成员函数,也可以是独立函数。

如果 dbx 环境变量 output_pretty_print 设置为 on,-p 会传递到 print 命令、 rprint 命令或 display 命令中作为缺省选项。可使用 +p 来覆盖此行为。

另外需要考虑以下各项: