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 |
r | run 的简写,运行被调试的程序<br/>如果此前没有设置过断点,则完整执行整个程序<br/>如果有断点,则程序暂停在第一个可用断点处 | (gdb) r |
c | continue 的简写,继续执行被调试过的程序,<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, n | s:执行一行源程序代码,如果此行代码中函数调用,则进入该函数<br/>n:执行一行源程序代码,此行代码中的函数调用也一并执行<br/>s 相当于其他调试器中的Step Into(单步跟踪进入) <br/>n 相当于其他调试器中的Step Over(单步跟踪) <br/>这两个命令必须在有源代码调试信息的情况下才可以使用<br/>(GCC 编译时使用-g 参数) | (gdb) s<br/>(gdb) n |
si, ni | si命令类似于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 |
i | info的简写,显示各类信息 | (gdb) i r<br/>(gdb) i b<br/>(gdb) info break |
q | quit的简写,退出GDB 调试环境 | (gdb) q |
help [命令名称] | GDB帮助命令,提供对GDB名种命令的解释说明。<br/>如果指定了“命令名称”参数,则显示该命令的详细说明;<br/>如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。 | (gdb) help display |