讲师博文
gdb使用流程 来源 : 未知     2018-09-21

这里给出了一个短小的程序,由此带领读者熟悉 gdb 的使用流程。建议读者能够动手实际操作一下。

首先,打开Linux 下的编辑器vi 或者emacs,编辑如下代码。

/*test.c*/

#include

int sum(int m);

int main()

{

int i, n = 0;

sum(50);

for(i = 1; i<= 50; i++)

{

n += i;

}

printf("The sum of 1-50 is %d \n", n );

}

int sum(int m)

{

int i, n = 0;

for (i = 1; i <= m; i++)

{

n += i;

printf("The sum of 1-m is %d\n", n);

}

}

在保存退出后首先使用 gcc 对test.c 进行编译,注意一定要加上选项"-g",这样编译出的可执行代码中才包含调试信息,否则之后gdb 无法载入该可执行文件。

[root@localhost gdb]# gcc -g test.c -o test

虽然这段程序没有错误,但调试完全正确的程序可以更加了解gdb 的使用流程。接下来就启动gdb 进行调试。注意,gdb 进行调试的是可执行文件,而不是如".c"的源代码,因此,需要先通过gcc 编译生成可执行文件才能用gdb 进行调试。

[root@localhost gdb]# gdb test

GNU gdb Red Hat Linux (6.3.0.0-1.21rh)

Copyright 2004 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type "show warranty" for details.

This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library

"/lib/libthread_db.so.1".

(gdb)

可以看出,在gdb 的启动画面中指出了gdb 的版本号、使用的库文件等信息,接下来就进入了由"(gdb)"开头的命令行界面了。

(1)查看文件。

在 gdb 中键入"l"(list)就可以查看所载入的文件,如下所示。

(gdb) l

1 #include

2 int sum(int m);

3 int main()

4 {

5 int i,n = 0;

6 sum(50);

7 for(i = 1; i <= 50; i++)

8 {

9 n += i;

10 }

(gdb) l

11 printf("The sum of 1~50 is %d \n", n );

12

13 }

14 int sum(int m)

15 {

16 int i, n = 0;

17 for(i = 1; i <= m; i++)

18 {

19 n += i;

20 }

21 printf("The sum of 1~m is = %d\n", n);

20 }

可以看出,gdb 列出的源代码中明确地给出了对应的行号,这样就可以大大地方便代码的定位。

(2)设置断点。

设置断点是调试程序中一个非常重要的手段,它可以使程序运行到一定位置时暂停。因此,程序员在该位置处可以方便地查看变量的值、堆栈情况等,从而找出代码的症结所在。

在 gdb 中设置断点非常简单,只需在"b"后加入对应的行号即可(这是常用的方式,另外还有其他方式设置断点),如下所示:

(gdb) b 6

Breakpoint 1 at 0x804846d: file test.c, line 6.

要注意的是,在gdb 中利用行号设置断点是指代码运行到对应行之前将其停止,如上例中,代码运行到第6 行之前暂停(并没有运行第6 行)。

(3)查看断点情况。

在设置完断点之后,用户可以键入"info b"来查看设置断点情况,在gdb 中可以设置多个断点。

(gdb) info b

Num Type Disp Enb Address What

1 breakpoint keep y 0x0804846d in main at test.c:6

用户在断点键入"backrace"(只输入"bt"即可)可以查到调用函数(堆栈)的情况,这个功能在程序调试之中使用非常广泛,经常用于排除错误或者监视调用堆栈的情况。

(gdb) b 19

(gdb) c

Breakpoin 2, sum(m=50) at test.c:19

19 printf("The sum of 1-m is %d\n", n);

(gdb) bt

#0 sum(m=50) at test.c:19 /* 停在test.c 的sum()函数,第19 行*/

#1 0x080483e8 in main() at test.c:6 /* test.c 的第6 行调用sum 函数*/

(4)运行代码。

接下来就可运行代码了,gdb 默认从首行开始运行代码,键入"r"(run)即可(若想从程序中指定行开始运行,可在r 后面加上行号)。

(gdb) r

Starting program: /root/workplace/gdb/test

Reading symbols from shared object read from target memory...done.

Loaded system supplied DSO at 0x5fb000

Breakpoint 1, main () at test.c:6

6 sum(50);

可以看到,程序运行到断点处就停止了。

(5)查看变量值。

在程序停止运行之后,程序员所要做的工作是查看断点处的相关变量值。在 gdb 中键入"p"+变量值即可,如下所示:

(gdb) p n

$1 = 0

(gdb) p i

$2 = 134518440

在此处,为什么变量"i"的值为如此奇怪的一个数字呢?原因就在于程序是在断点设置的对应行之前停止的,那么在此时,并没有把"i"的数值赋为零,而只是一个随机的数字。但变量"n"是在第4 行赋值的,故在此时已经为零。

(6)单步运行。

单步运行可以使用命令"n"(next)或"s"(step),它们之间的区别在于:若有函数调用的时候,"s"会进入该函数而"n"不会进入该函数。因此,"s"就类似于Uisual 等工具中的"step in","n"类似与Uisual等工具中的"step over"。它们的使用如下所示:

(gdb) n

The sum of 1-m is 1275

7 for (i = 1; i <= 50; i++)

(gdb) a

sum (m=50) at test.c:16

16 int i, n = 0;

可见,使用"n"后,程序显示函数sum()的运行结果并向下执行,而使用"s"后则进入sum()函数之中单步运行。

(7)恢复程序运行

在查看完所需变量及堆栈情况后,就可以使用命令"c"(continue)恢复程序的正常运行了。这时,它会把剩余还未执行的程序执行完,并显示剩余程序中的执行结果。以下是之前使用"n"命令恢复后的执行结果:

(gdb) c

Continuing.

The sum of 1-50 is :1275

Program exited with code 031.

可以看出,程序在运行完后退出,之后程序处于"停止状态"。

扫码申领本地嵌入式教学实录全套视频及配套源码

上一篇:嵌入式开发中的gzip打包命令

下一篇:Thumb 编程模型

400-611-6270

Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5京公海网安备11010802025203号