GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。

一般来说,GDB主要帮忙你完成下面四个方面的功能:

1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。

从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。

先用vim写一个示例程序(tst.c):

#include <stdio.h> int func(int n){    int sum=0, i;    for(i=0;i<n;i++)    {        sum+=i;    }    return sum;} void main(){    int i;    long result=0;    for(i=1;i<=100;i++)    {        result+=i;    }    printf("result[1-100]=%d \n", result);    printf("result[1-250]=%d \n", func(250));}   

编译生成可执行文件:

$ gcc -g tst.c -o tst # -g 选项的意思是加入调试信息

使用gdb调试(感性理解):

(体验好差,可以来这里看:https://blog.csdn.net/HaoZiHu...

$ gdb tst                 <----------启动GDB GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git       <-------显示GDB说明,不管它Copyright (C) 2018 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from tst...done.(gdb) l                  <-----------l命令相当于list,从第一行开始列出源码2    3    int func(int n)4    {5        int sum=0, i;6        for(i=0;i<n;i++)7        {8            sum+=i;9        }10        return sum;11    }(gdb)                   <-------------- 直接回车,重复上一次命令12    13    void main()14    {15        int i;16        int result=0;17        for(i=1;i<=100;i++)18        {19            result+=i;20        }21        printf("result[1-100]=%d /n", result);(gdb) break 15          <-------------- 设置断点,在源程序第15行设置断点Breakpoint 1 at 0x680: file tst.c, line 15.(gdb) break func        <-------------- 设置断点,在函数func()入口处Breakpoint 2 at 0x651: file tst.c, line 5.(gdb) info break        <--------------- 查看断点信息Num     Type           Disp Enb Address            What1       breakpoint     keep y   0x0000000000000680 in main at tst.c:152       breakpoint     keep y   0x0000000000000651 in func at tst.c:5(gdb) r                 <--------------- 运行程序,run命令简写Starting program: /home/jack/demo/gdb/tst Breakpoint 1, main () at tst.c:1616        int result=0;   <--------------- 在断点处停住(gdb) n                 <--------------- 单条语句执行,next命令简写17        for(i=1;i<=100;i++)(gdb) n19            result+=i;(gdb) n17        for(i=1;i<=100;i++)(gdb) n19            result+=i;(gdb) n17        for(i=1;i<=100;i++)(gdb) n19            result+=i;(gdb) c                 <--------------- 继续运行命令,continue命令简写Continuing.Breakpoint 2, func (n=250) at tst.c:55        int sum=0, i;(gdb) n6        for(i=0;i<n;i++)(gdb) n8            sum+=i;(gdb) p i              <--------------- 打印变量的值 print命令缩写$1 = 0(gdb) p sum$2 = 0(gdb) bt               <--------------- 查看函数堆栈#0  func (n=250) at tst.c:8#1  0x00005555555546c0 in main () at tst.c:22(gdb) finish           <---------------- 退出函数Run till exit from #0  func (n=250) at tst.c:80x00005555555546c0 in main () at tst.c:2222        printf("result[1-250]=%d /n", func(250));Value returned is $3 = 31125(gdb) cContinuing.result[1-100]=5050 result[1-250]=31125 [Inferior 1 (process 7775) exited with code 026] <-------------- 程序退出,调试结束(gdb) q               <--------------- 退出gdb

在此处我们简单总结一下gdb的命令(<br/>是换行的意思,SF的markdown没有内嵌这个元素......):

命令解释实例
file <文件名>加载被调试的可执行程序文件(gdb) file gdb_sample
rrun的简写,运行被调试的程序<br/>如果此前没有设置过断点,则完整执行整个程序<br/>如果有断点,则程序暂停在第一个可用断点处(gdb) r
ccontinue的简写,继续执行被调试过的程序,<br/>直至下一个断点停在第一个可用断点处(gdb) c
b <行号><br/>b <函数名称><br/>b <函数名称><br/>b <代码地址><br/>d [编号]b:break的简写,设置断点,可以使用行号、函数名称<br/>或执行地址等方式来设置断点位置<br/>其中在函数名称前加*符号表示将断点设置在"由编译器<br/>生成的prolog"代码处,如果不了解汇编,可以不管此用法<br/>d:delete的简写,删除指定编号的某个断点,<br/>或删除所有断点,断点编号从1开始递增(gdb) b 8<br/>(gdb) b main<br/>(gdb) b main<br/>(gdb) b 0x3422<br/>(gdb) d 1
s, ns:执行一行源程序代码,如果此行代码中函数调用,则进入该函数<br/>n:执行一行源程序代码,此行代码中的函数调用也一并执行<br/>s 相当于其他调试器中的Step Into(单步跟踪进入)<br/>n 相当于其他调试器中的Step Over(单步跟踪)<br/>这两个命令必须在有源代码调试信息的情况下才可以使用<br/>(GCC 编译时使用-g参数)(gdb) s<br/>(gdb) n
si, nisi命令类似于s命令,ni命令类似于n命令,不同的是:<br/>这两条命令所针对的是汇编指令<br/>而s/n针对的是源代码(gdb) si<br/>(gdb) ni
p <变量名称>print的简称,显示指定变量(临时或全局变量)的值(gdb) p i<br/>(gdb) p cardPlay
display ...<br/>undisplay <编号>display 设置程序中断后欲显示的数据及其格式<br/>例如,如果希望每次程序中断后可以看到即将被执行的下一条汇编指令,可以使用命令"display /i $pc"<br/>其中 $pc代表当前汇编指令,/i表示以十六进行显示,当需要关心汇编代码时,此命令相当有用<br/>undisplay,取消先前的display设置,编号从1开始递增(gdb) display /i $pc<br/>(gdb) undisplay 1
iinfo的简写,显示各类信息(gdb) i r<br/>(gdb) i b<br/>(gdb) info break
qquit的简写,退出GDB调试环境(gdb) q
help [命令名称]GDB帮助命令,提供对GDB名种命令的解释说明。<br/>如果指定了“命令名称”参数,则显示该命令的详细说明;<br/>如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。(gdb) help display