本文共 4094 字,大约阅读时间需要 13 分钟。
本节书摘来异步社区《嵌入式 Linux C 语言应用程序设计(修订版)》一书中的第2章,第2.4节,作者:华清远见嵌入式培训中心,孙琼,更多章节内容可以访问云栖社区“异步社区”公众号查看
嵌入式 Linux C 语言应用程序设计(修订版)
在程序编译通过生成可执行文件之后,就进入了程序的调试环节。调试一直来是程序开发中的重中之重,如何使程序员能够迅速找到错误的原因是一款调试器的目标。GDB是GNU开源组织发布的一个强大的Linux下的程序调试工具,它是一种强大的命令行调试工具。
一个出色的调试器需要有以下几项功能。
能够运行程序,设置所有能影响程序运行的参数。
能够让程序让指定的条件下停止。能够在程序停止时检查所有参数的情况。能够根据指定条件改变程序的运行。下面通过一个简单的实例使读者对GDB有一个感性的认识,这里所介绍的指令都是GDB中最为基本也是最为常用的指令,希望读者能够动手操作,掌握GDB的使用方法。 首先,有以下程序段。
#include/*子函数add:将自然数从1~m相加*/int add(int m){ int i,n=0; for(i=1; i<=m;i++) n += i; printf("The sum of 1-%d in add is %d\n", m,n);}int main(){ int i,n=0; add(50); for(i=1; i<=50; i++) n += i; printf("The sum of 1-50 is %d \n", n );}```注意将此程序用GCC进行编译时要加上“-g”选项。1.进入GDB进入GDB只需输入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 arewelcome 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)”开头的命令行界面了。 2.查看文件
在GDB中键入‘l’(list)就可以查看所载入的文件,如下所示:(gdb) l4 {5 int i,n=0;6 for(i=1; i<=m;i++)7 n += i;8 printf("The sum of 1-%d in add is %d\n", m,n);9 }1011 int main()12 {13 int i,n=0;(gdb) l14 add(50);15 for(i=1; i<=50; i++)16 {17 n += i;18 }19 printf("The sum of 1-50 is %d \n", n );20 21 }22```可以看出,GDB列出的源代码中明确地给出了对应的行号,这样可以大大地方便代码的定位。注意 在一般情况下,源代码中的行号与用户书写程序中的行号是一致的,但有时由于用户的某些编译选项会导致行号不一致的情况,因此,一定要查看在GDB中的行号。3.设置断点设置断点可以使程序到一定位置暂停它的运行,程序员在该位置处可以方便地查看变量的值、堆栈情况等,从而找出代码的症结所在。在GDB中设置断点非常简单,只需在“b”后加入对应的行号即可(这是最常用的方式,另外还有其他方式设置断点),其命令如下所示:
(gdb) b 6
Breakpoint 1 at 0x804846d: file test.c, line 6.`
要注意的是,在GDB中利用行号设置断点是指代码运行到对应行之前暂停,如上例中,代码运行到第5行之前暂停(并没有运行第5行)。 4.查看断点处情况
在设置完断点之后,用户可以键入“info b”来查看设置断点情况,在GDB中可以设置多个断点。(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x0804846d in main at test.c:6```5.运行代码接下来就可运行代码了,GDB默认从首行开始运行代码,可键入“r”(run)即可,在“r”后面加上行号即可从程序中指定行开始运行。
(gdb) r
Starting program: /home/yul/book/testBreakpoint 1, add (m=50) at test.c:6
6 for(i=1; i<=m;i++)`
可以看到,程序运行到断点处就停止了。 6.查看变量值
在程序停止运行之后,程序员需要查看断点处的相关变量值。在GDB中只需键入“p+变量值”即可,如下所示:(gdb) p n$1 = 0(gdb) p i$2 = 134518440```在此处,为什么变量“i”的值为如此奇怪的一个数字呢?原因就在于程序是在断点设置的对应行之前停止的,那么在此时,并没有把“i”的数值赋为0,而只是一个随机的数字。但变量“n”是在第5行赋值的,故在此时已经为0。小技巧 GDB在显示变量值时都会在对应值之前加上“$N”标记,它是当前变量值的引用标记,所以以后若想再次引用此变量就可以直接写作“$N”,而无需写冗长的变量名。7.观察变量在某一循环处,程序员往往希望能够观察一个变量的变化情况,这时就可以键入命令“watch”来观察变量的变化情况,如下所示:
(gdb) watch n
Hardware watchpoint 2: n`
可以看到,GDB在“n”设置了观察点。 注意 在此处必须键入完整的命令“watch”,因为在GDB中有不少以‘w’开头的命令,如“where”、“while”等。
8.单步运行单步运行是指一次只运行一条语句,这样可以方便程序员来查看程序运行的结果,在此处只需键入“n”(next)即可。(gdb) n7 n += i;(gdb) nHardware watchpoint 2: nOld value = 15New value = 21```可以看到,随着程序的单步运行,当“n”的值发生变化时,GDB就会自动显示出n的变化情况。9.程序继续运行命令“c”(continue)可以使GDB继续运行以下的程序,程序在再次遇到断点时停止,如下所示:
(gdb) c
Continuing.The sum of 1-50 is 1275Program exited with code 031.`
(gdb) q[root@localhost gcc]```到此为止,使用GDB的整体过程已经结束了。以上所讲述的命令是GDB中最为常见的命令,下面几节将会详细讲解GDB的命令。####2.4.2 设置/删除断点GDB中有丰富的断点设置、删除命令,可以满足用户各个方面的需求。表2.8列出了GDB中常见的断点设置及删除命令。小知识 在多线程的程序中,观察点的作用很有限,gdb只能观察在一个线程中的表达式的值。如果用户确信表达式只被当前线程所存取,那么使用观察点才有效。gdb不能注意一个非当前线程对表达式值的改变。####2.4.3 数据相关命令在GDB中也有丰富的数据显示相关命令,他们可以使用户可以以各种形式显示所要查看的数据,数据相关命令如表2.9所示。
小技巧 在使用print命令时,可以对变量按指定格式进行输出,其命令格式为:print /变量名+格式其中格式有以下几种方式。X:十六进制;d:十进制;u:无符号数;o:八进制;T:二进制;a:十六进制打印;c:字符格式;f:浮点数。####2.4.4 调试运行环境相关命令在GDB中控制程序的运行也是非常方便地,用户可以自行设定变量值、调用函数等,其具体命令如表2.10所示。
####2.4.5 堆栈相关命令gdb中也提供了多种堆栈相关的命令,可以查看堆栈的情况、寄存器的情况等,其具体命令如表2.11所示。![]()
![]()
转载地址:http://cbfkm.baihongyu.com/