一起talk GDB吧(第五回:GDB查看信息)

来源:互联网 发布:windows 虚拟桌面软件 编辑:程序博客网 时间:2024/04/25 16:30


各位看官们,大家好,上一回中我们说的是GDB的调用栈调试功能,并且说了如何使用GDB进行查看调用

栈。这一回中,我们继续介绍GDB的调试功能:查看信息。当然了,我们也会介绍如何使用GDB查看程序

运行时的信息。闲话休提,言归正转。让我们一起talk GDB吧!


看官们,我们在调试的时候需要查看程序中的相关信息,比如变量值。GDB提供了查看信息的功能,这些

查看功能主要有:查看源代码和变量值,跟踪变量。下面我们详细说说这些查看功能。


查看源代码:list 或者list n.list默认列出源代码中前10的内容,它会从第一行开始显示程序源代码,每次

显示10行,如果再执行一次list命令,它会接着上一次的行数继续显示源代码。list n表示显示10行源代码,

其中第n行位于这10行代码的中间。


查看变量值:info(缩写为i)。例子:i locals表示查看程序运行时所有变量的值。info显示的是程序中所有变

量的值,如果只想看某个变量的值,那么使用命令:print(缩写为p)可以打印变个变量的值,例子:p iVal

表示查看变量iVal的值。该功能经常和断点配合使用,如果想查看程序运行过程中某个变量的值,可以先让程

序停止下来,然后再使用该功能查看变量的值。


跟踪变量:display.例子:display index表示跟踪显示变量index的值。GDB提供的该功能可以看作是对查看

变量功能的补充。因为使用p和i显示变量值时,只会显示一次,而display可以一直显示变量的值。该功能可

以用来在循环语句中显示循环中的索引值,循环每执行一次,它就能自动显示一次,不需要手动查看索引值,

这对跟踪数组越界很有用。如果不想跟踪变量变量了,使用undisply可以取消跟踪显示。例子undisply index

表示不再跟踪显示变量index的值。


古诗云:纸上得来终觉浅,绝知此事要躬行。我们举个例子来实践一下:

     1    #include<stdio.h>     2         3    void exchange(int a, int b)     4    {     5        int s = 0;     6         7        s = a;     8        a = b;     9        b = s;    10    }    11        12    int main()    13    {    14        int a,b,i;    15        a = 3;    16        b = 5;    17        i = 0;    18        19        printf("Before change a = %d,b = %d  \n",a,b);    20        exchange(a,b);    21        printf("After change  a = %d,b = %d  \n",a,b);    22        23        while(i++ < 3)    24            printf("i =%d \n",i);    25        26        return 0;    27    }


1.编写程序。打开VIM,输入上面的程序,并且保存到m.c文件中

2.编译程序。在终端中输入:gcc -g m.c -o s

3.运行程序。在终端中输入:./s ,得到以下运行结果:

Before change a = 3,b = 5  

After change  a = 3,b = 5  

i =1

i =2

i =3

通过结果我们可以看到,i的值打印没有问题,不过exchange函数的运行结果不正确,a和b交换前后的

值完全一样。看来程序存在逻辑问题,我们使用GDB进行调试。


4.调试程序。在终端中输入:gdb s。

(gdb) b exchange   //在函数exchange哪里设置位置断点

Breakpoint 1 at 0x8048423: file m.c, line 5.

(gdb) run          //启动调试,遇到断点会停止

Starting program: xxx/test/s

Before change a = 3,b = 5  


Breakpoint 1, exchange (a=3, b=5) at m.c:5   //在断点处停止

5        int s = 0;

(gdb) n           //单步调试

7        s = a;

(gdb)             //输入回车,继续单步调试

8         a = b;

(gdb)             //输入回车,继续单步调试

9        b = s;

(gdb)             //输入回车,继续单步调试

10    }

(gdb) p a         //查看变量a的值

$1 = 5

(gdb) p b         //查看变量b的值

$2 = 3


通过调试的结果,大家可以看到在断点停止处哪里,a=3, b=5。到函数结束处我们通过p查看它们的值时

已经发生交换。但是函数结束后,它们的值还没有交换。大家能知道什么原因吗?这个是C语言中典型的

传值调用,学习过C语言的,肯定知道其中的原因,我就不多说了。


接下来,我们再体会一下路径变量的功能。

(gdb) display i //跟踪变量 i

(gdb) n         //单步调试,  省略前面单步调试的结果

i =1            //程序运行进显示变量的值

23        while(i++ < 3)

1: i = 1       //跟踪显示变量的值

(gdb)          //输入回车,继续单步调试

24            printf("i =%d \n",i);

1: i = 2        

(gdb)         //输入回车,继续单步调试

i =2

23        while(i++ < 3)

1: i = 2

(gdb)         //输入回车,继续单步调试

24            printf("i =%d \n",i);

1: i = 3

(gdb)         //输入回车,继续单步调试

i =3

23        while(i++ < 3)

1: i = 3

(gdb)          //输入回车,继续单步调试

26        return 0;


大家从调试的结果中可以看到,每次运行单步调试都会显示i的值,而且路径显示的值和程序运行时打印出

来的值一样。这便是跟踪变量的功能。


我们通过例子说明了如何使用GDB提供的查看信息功能。通过查看程序运行时的信息,可以方便地找出程序

中的错误,希望大家能够灵活使用该功能,进而提高调试程序的效率。


看官们,关于GDB的内容,今天咱们就说到这里。欲知后事如何,且听下回分解!



0 0
原创粉丝点击