GDB 基本知识

来源:互联网 发布:斑竹网络意思 编辑:程序博客网 时间:2024/06/05 03:16

1、GDB 是什么?
 GDB(GNU symbolic debugger)简单地说就是一个调试工具。它是一个受通用公共许可证即GPL保护的自由软件。

2、GDB特性

  象所有的调试器一样,GDB可以让你调试一个程序,包括让程序在你希望的地方停下,此时你可以查看变量,寄存器,内存及堆栈。更进一步你可以修改变量及内存值。GDB是一个功能很强大的调试器,它可以调试多种语言。在此我们仅涉及C和C++的调试,而不包括其它语言。还有一点要说明的是,GDB是一个调试器,而不象VC一样是一个集成环境。你可以使用一些前端工具如XXGDB,DDD等。他们都有图形化界面,因此使用更方便,但它们仅是GDB的一层外壳。因此,你仍应熟悉GDB命令。事实上,当你使用这些图形化界面时间较长时,你才会发现熟悉GDB命令的重要性。下面我们将结合简单的例子,来介绍GDB的一些重要的常用命令。在你调试你的程序之前,当你编译你的源程序时,不要忘了-g选项或其它相应的选项,才能将调试信息加到你要调试的程序中。例如:gcc -g -o hello hello.c 。

3、GDB常用命令简介

  GDB的命令很多,本文不会全部介绍,仅会介绍一些最常用的。在介绍之前,先介绍GDB中的一个非常有用的功能:补齐功能。它就如同Linux下SHELL中的命令补齐一样。当你输入一个命令的前几个字符,然后输入TAB键,如果没有其它命令的前几个字符与此相同,SHELL将补齐此命令。如果有其它命令的前几个字符与此相同,你会听到一声警告声,再输入TAB键,SHELL将所有前几个字符与此相同的命令全部列出。而GDB中的补齐功能不仅能补齐GDB命令,而且能补齐参数。
  本文将先介绍常用的命令,然后结合一个具体的例子来演示如何实际使用这些命令。下面的所有命令除了第一条启动GDB命令是在SHELL下输入的,其余都是GDB内的命令。大部分GDB内的命令都可以仅输入前几个字符,只要不与其它指令冲突。如quit可以简写为q,因为以q打头的命令只有quit。List可以简写为l,等等


3.1 启动GDB        ->    gdb hello

3.2 载入程序         ->    file hello

      退出GDB         ->   quit

3.3 运行程序         ->   run  或 r

3.4 查看程序信息             ->    info
    (可用以查看断点信息)

3.4.1 查看断点信息       ->    info br
3.4.2 查看当前源程序   ->    info source
3.4.3 查看堆栈信息       ->    info stack
           用这条指令你可以看清楚程序的调用层次关系。
3.4.4 查看当前的参数   ->    info args

3.5 列出源一段源程序                                                        ->    list  或 l
3.5.1 列出某个函数                                                          ->    list FUNCTION
3.5.2 以当前源文件的某行为中间显示一段源程序      ->    list LINENUM
3.5.3 接着前一次继续显示                                              ->    list
3.5.4 显示前一次之前的源程序                                      ->    list -
3.5.5 显示另一个文件的一段程序                                  ->    list FILENAME:FUNCTION 或 list FILENAME:LINENUM

3.6 设置断点                                                                                                         ->   break
3.6.1 在函数入口设置断点                                                                               ->   break FUNCTION
3.6.2 在当前源文件的某一行上设置断点                                                       ->   break LINENUM
3.6.3 在另一个源文件的某一行上设置断点                                                   ->   break FILENAME:LINENUM
3.6.4 在某个地址上设置断点(当你调试的程序没有源程序时,这很有用)   ->   break *ADDRESS
3.6.5 条件断点                                                                                                   ->   break ...if COND
  COND是一个布尔条件表达式,语法与C语言中的一样。

3.7 其它断点操作
  GDB给每个断点赋上一个整数数字,这个数字在操作断点时起到重要作用,它实际上就代表相应的断点。

        GDB中的断点有四种状态:
  有效(Enabled)
  禁止(Disabled)
  一次有效(Enabled once)
  有效后删除(Enabled for deletion)

  在上面的四个状态有效和禁止都很好理解,禁止就是让断点暂时失效。一次有效就是当程序在此断点断下后,断点状态自动变为禁止状态。有效后删除就是当程序在此断点断下后,断点被删除。实际上,后两种状态一般不会碰到。
  当你设置一个断点后,它的缺省状态是有效。你可以用enable和disable指令来设置断点的状态为有效或禁止。

        例如,如果你想禁止2号断点,可以用下面的指令:disable 2
        相应的,如果想删除2号断点,可以有下面的指令:delete 2

3.8 设置监视点 -> watch EXPRESSION
  要注意的是,监视点有硬件和软件两种方式,Linux尽可能用硬件方式,因为硬件方式在速度上要大大快于软件方式。软件方式由于要在每次执行一条指令后都要检查所要监视的值是否被改变,因此它的执行速度会大大降低。同时它也无法设置成被读时让程序断下,因为读操作不会改变值,所以GDB无法检测到读操作。幸运的是,目前的PC机基本都支持硬件方式。如果你想确认一下你的机器是否支持硬件,你可以在调试程序时用watch设置一个监视点,如果GDB向你显示:
   Hardware watchpoint NUM: EXPR
  那么你可以放心了,你的机器支持硬件方式。

3.9 检查数据    ->   print exp
  print指令打印exp表达式的值。表达式exp中的变量必须是全局变量或当前堆栈区可见的变量。否则GDB会显示象下面的一条信息:
   No symbol "varible" in current context

3.10 修改变量值   ->   set varible=value

3.11 检查内存值   ->   x /NFU ADDR
       其中N代表重复数,F代表输出格式(见2.13),U代表每个数据单位的大小。

       U可以取如下值:
b :字节(byte)
h :双字节数值
w :四字节数值
g :八字节数值
  因此,上面的指令可以这样解释:从ADDR地址开始,以F格式显示N个U数值。

3.12 输出格式
  缺省情况下,输出格式依赖于它的数据类型。但你可以改变输出格式。当你使用print命令时,可以用一个参数/F来选择输出的打印格式。F可以是以下的一些值:
  'x' 16进制整数格式
  'd' 有符号十进制整数格式
  'u' 无符号十进制整数格式
  'f' 浮点数格式

3.13 单步执行指令   ->   step(s)和next(n)。

        Step可以让你跟踪进入一个函数,而next指令则不会进入函数。

3.14 继续执行指令   ->   continue  或 c

3.15 帮助指令           ->   help
  例如,想知道list指令用法,输入help list

4.一个简单的例子

  上面仅是GDB常用指令的简单介绍。本节将结合一个简单的例子,向大家演示这些常用指令的具体应用。这是一个冒泡排序算法的程序,这个例子的目的仅仅是演示,并不是实际调试。将下面的源程序存为bubble.c文件,并编译好。
#include
#define MAX_RECORD_NUMBER 10
int record[MAX_RECORD_NUMBER] =
{12,76,48,62,94,17,37,52,69,32};
swap(int * x , int * y )
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
int main()
{
int i,j;
for( i = 0 ; i i; j--)
if( record[j] : 12 76 48 62
上面的指令查看4个4字节数,以整数方式显示。可以看到这与reocrd值是相附的。
(gdb) x/4bb record
0x8049580 : 12 0 0 0
显示4个单字节数,以字节当时显示。上面的4个字节值正好是record数组第一个整数值,因为整数是4字节,而且intel机器的数值是低字节在前。
改变变量值也很简单,如果想将reocrd数组第一个值该为1,
(gdb) set record[0]=1
看一下值是否改变了。
(gdb) p record
$10 = {1, 76, 48, 62, 94, 17, 32, 37, 52, 69}
第一个值以改成了1。
  以上简单地介绍了一些常用的GDB指令,由于篇幅所限,我们无法涉及GDB所有指令及GDB其它许多功能,读者应当自己在实践中不断地学习。Linux系统中会有详细的GDB的资料,你可以用info gdb来查阅这些资料。


原文:http://blog.chinaunix.net/u/27340/showart_325039.html

原创粉丝点击