Skip to content

LV083-gdb-display

一、display

和 print 命令一样,display 命令也用于调试阶段查看某个变量或表达式的值,它们的区别是,使用 display 命令查看变量或表达式的值,每当程序暂停执行(例如单步执行)时,GDB 调试器都会自动帮我们打印出来,而 print 命令则不会。

也就是说,使用 1 次 print 命令只能查看 1 次某个变量或表达式的值,而同样使用 1 次 display 命令,每次程序暂停执行时都会自动打印出目标变量或表达式的值。因此,当我们想频繁查看某个变量或表达式的值从而观察它的变化情况时,使用 display 命令可以一劳永逸。

1. 语法格式

display 命令没有缩写形式,常用的语法格式如下 2 种:

shell
(gdb) display expr
(gdb) display/fmt expr

其中,expr 表示要查看的目标变量或表达式;参数 fmt 用于指定输出变量或表达式的格式,表 1 罗列了常用的一些 fmt 参数。

表 1 /fmt 常用的值
/fmt 功 能
/x 以十六进制的形式打印出整数。
/d 以有符号、十进制的形式打印出整数。
/u 以无符号、十进制的形式打印出整数。
/o 以八进制的形式打印出整数。
/t 以二进制的形式打印出整数。
/f 以浮点数的形式打印变量或表达式的值。
/c 以字符形式打印变量或表达式的值。

Tips:display 命令和 /fmt 之间不要留有空格。以 /x 为例,应写为 (gdb) display/x expr

2. 自动显示列表

对于使用 display 命令查看的目标变量或表达式,都会被记录在一张列表(称为自动显示列表)中。通过执行info dispaly命令,可以打印出这张表:

shell
(gdb) info display

一般是会有如下几列显示:

shell
Auto-display expressions now in effect:
Num Enb Expression
1   y   num

其中,各列的含义为:

  • Num 列为各变量或表达式的编号,GDB 调试器为每个变量或表达式都分配有唯一的编号;
  • Enb 列表示当前各个变量(表达式)是处于激活状态还是禁用状态,如果处于激活状态(用 y 表示),则每次程序停止执行,该变量的值都会被打印出来;反之,如果处于禁用状态(用 n 表示),则该变量(表达式)的值不会被打印。
  • Expression 列:表示查看的变量或表达式。

3. 删除、禁用与激活

对于不需要再打印值的变量或表达式,可以将其删除或者禁用。

3.1 undisplay/delete

通过执行如下命令,即可删除自动显示列表中的变量或表达式:

shell
(gdb) undisplay num...
(gdb) delete display num...

参数 num... 表示目标变量或表达式的编号,编号的个数可以是多个。例如:

shell
(gdb) undisplay 1
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
2:   y   /t result
(gdb)

可以看到,借助 undisplay 命令成功删除了编号为 1 的 num 变量。

3.2 disable

通过执行如下命令,可以禁用自动显示列表中处于激活状态下的变量或表达式:

shell
(gdb) disable display num...

num... 表示要禁用的变量或表达式的编号,编号的个数可以是多个,表示一次性禁用多个变量或表达式。例如

shell
(gdb) disable display 2
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
2:   n   /t result
(gdb)

可以看到,编号为 2 的 result 变量的 Enb 由 y 变成了 n。处于禁用状态的变量或表达式,程序停止执行时将不再自动打印出它们的值。

3.3 enable

当然根据需要,也可以激活当前处于禁用状态的变量或表达式,执行如下命令即可:

shell
(gdb) enable display num...

参数 num... 表示要激活的变量或表达式的编号,编号的个数可以是多个,表示一次性激活多个变量或表达式。例如

shell
(gdb) enable display 2
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
2:  y /t result
(gdb)

总的来说,每次程序停止执行时,GDB 调试器会将自动显示列表中处于激活状态下的变量或表达式的值打印出来,display 命令可以实现在查看目标变量或表达式的值的同时,将其添加到自动显示列表中,而 print 命令则只会打印出目标变量或表达式的值。

二、使用示例

1. 测试程序

c
#include <stdio.h>
int main(int argc, const char *argv[]) {
    int num, result = 0, i = 0;
    scanf("%d", &num);
    while (i <= num) {
        result += i;
        i++;
    }
    printf("result = %d\n", result);
    return 0;
}

我们在ubuntu中测试,所以直接用下面的命令编译:

shell
cd ~/workspace/c-learning/02-c-basic/21-debug
gcc 035-gdb-display.c -g

2. 调试示例

shell
 sumu@virtual-machine:~/workspace/c-learning/02-c-basic/21-debug [main  +1 ~0 -0 !]
$ gdb a.out -q
Reading symbols from a.out...
(gdb) l                   # <=== 1. 显示源码
1       #include <stdio.h>
2       int main(int argc, const char *argv[]) {
3           int num, result = 0, i = 0;
4           scanf("%d", &num);
5           while (i <= num) {
6               result += i;
7               i++;
8           }
9           printf("result = %d\n", result);
10          return 0;
(gdb) b 4                 # <=== 2. 第4行打断点
Breakpoint 1 at 0x11b9: file 035-gdb-display.c, line 4.
(gdb) b 9                 # <=== 3. 第9行打断点
Breakpoint 2 at 0x11e5: file 035-gdb-display.c, line 9.
(gdb) r                   # <=== 4. 运行程序
Starting program: /home/sumu/workspace/c-learning/02-c-basic/21-debug/a.out 

Breakpoint 1, main (argc=1, argv=0x7fffffffce28) at 035-gdb-display.c:4
4           scanf("%d", &num);
(gdb) display num         # <=== 5. 显示num的值
1: num = 21845
(gdb) display/t result    # <=== 6. 显示result的值
2: /t result = 0
(gdb) n                   # <=== 7. 执行1行代码
3                         # <=== 8. 输入num的值
5           while (i <= num) {
1: num = 3                # <=== 输入完毕后程序停下,自动打印了前面添加到自动显示列表中的变量的值
2: /t result = 0
(gdb) c                   # <=== 9. 继续运行,到第9行停下
Continuing.

Breakpoint 2, main (argc=1, argv=0x7fffffffce28) at 035-gdb-display.c:9
9           printf("result = %d\n", result);
1: num = 3                # <=== 10. 再次自动打印了前面添加到自动显示列表中的变量的值
2: /t result = 110
(gdb) info display        # <=== 11. 查看自动变量列表
Auto-display expressions now in effect:
Num Enb Expression
1:   y  num
2:   y  /t result
(gdb)