gdb简约入门

31次阅读

共计 4195 个字符,预计需要花费 11 分钟才能阅读完成。

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            What
1       breakpoint     keep y   0x0000000000000680 in main at tst.c:15
2       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:16
16        int result=0;   <--------------- 在断点处停住


(gdb) n                 <--------------- 单条语句执行,next 命令简写
17        for(i=1;i<=100;i++)
(gdb) n
19            result+=i;
(gdb) n
17        for(i=1;i<=100;i++)
(gdb) n
19            result+=i;
(gdb) n
17        for(i=1;i<=100;i++)
(gdb) n
19            result+=i;


(gdb) c                 <--------------- 继续运行命令,continue 命令简写
Continuing.

Breakpoint 2, func (n=250) at tst.c:5
5        int sum=0, i;


(gdb) n
6        for(i=0;i<n;i++)
(gdb) n
8            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:8
0x00005555555546c0 in main () at tst.c:22
22        printf("result[1-250]=%d /n", func(250));
Value returned is $3 = 31125

(gdb) c
Continuing.
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

正文完
 0