一、说明

        GDB(GNU Debugger)是UNIX及UNIX-like下的强大调试工具,可以调试ada, c, c++, asm, minimal, d, fortran, objective-c, go, java,pascal等语言。本文介绍GDB启动调试的方式。

二、Ubuntu上安装gdb。

        在root用户权限下:

root@huatec:~# apt-get update
root@huatec:
~# apt-get install gdb
Do you want to
continue? [Y/n] y
......

安装好gdb了。



三、GDB的简单使用。

        用root权限的Terminal(或一般权限的Terminal)的vi编辑器编写一个C程序mytest.cpp:

#include <stdio.h>
int func(int n)
{
         int sum=0,i;
        for(i=0; i<n; i++)
        {
                sum+=i;
        }
         return sum;
 }
 
int main()
{
        int i;
        int 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) );
}
(1) 在可执行文件中加入源码信息

这个过程通过gcc来完成:

gcc –o  test_gdb  mytest.c  -g

-o选项的作用是:对命令输出结果进行导入操作,这里是把gcc –o test_gdb mytest.c -g的操作结果输出到文件atest(文件名可以自定义)中进行保存。

-g选项的作用是:在可执行文件中加入源码信息,比如:可执行文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件都嵌入到可执行文件中,而是在调试时必须保证gdb能找到源文件。

3.1  进入gdb

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb test_gdb
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 a...done.
(gdb) 

如下图所示:

gdb提供一个类似Shell的命令行环境,上面的(gdb)就是提示符,在提示符后面输入gdb的相应命令就可以实现其对应的功能。

3.2  gdb调试常用命令

[1] start     ( start命令开始执行程序 ):

start后,gdb提示准备执行test_gdb.cpp程序的第16行代码。就是程序的第一条执行语句。

[2] 单步执行(n)    ( next命令开始从当前行执行一步 ):

(gdb) start
Temporary breakpoint 1 at 0x1187: file mytest.cpp, line 16.
Starting program: /home/huatec/test_gdb

Temporary breakpoint 1, main () at mytest.cpp:16
16            int result = 0;
(gdb) list
11    
12    
13    int main()
14    {
15            int i;
16            int result = 0;
17            for(i=1; i<=100; i++)
18            {
19                    result += i;
20            }
(gdb) n
17            for(i=1; i<=100; i++)
(gdb) n
19                    result += i;
(gdb) n
17            for(i=1; i<=100; i++)
(gdb)

  在start命令后,每输入一个n就能够单步执行一条语句(输入一个命令后,直接回车表示最近输入命令的含义)。当程序执行完时,可以输入quit命令来退出gdb模式。

[3] gdb断点调试

[ breakpoint,continue和display ]

(gdb) start
Temporary breakpoint 1 at 0x1187: file mytest.cpp, line 16.
Starting program: /home/huatec/test_gdb

Temporary breakpoint 1, main () at mytest.cpp:16
16            int result = 0;
(gdb) l
11    
12    
13    int main()
14    {
15            int i;
16            int result = 0;
17            for(i=1; i<=100; i++)
18            {
19                    result += i;
20            }
(gdb) b 19
Breakpoint 2 at 0x55555555519b: file mytest.cpp, line 19.
(gdb) c
Continuing.

Breakpoint 2, main () at mytest.cpp:19
19                    result += i;
(gdb) display result
1: result = 0
(gdb)

  b 19是breakpoint  19的简写(breakpoint的参数也可以以是某个函数名,表示在此函数处设置一个断点),表示在程序第19行设置一个断点。c是continue的缩写,表示继续运行程序,程序会在设置断点处停下来。display result表示将result的值显示出来(undisplay取消对变量的跟踪),然后再输入单步调试命令n(next)就可以使程序继续运行。

  可见断点有助于快速跳过没有问题的代码,然后在有问题的代码上慢慢走慢慢分析,“断点加单步”是使用调试器的基本方法。

[4]info

  一次调试可以设置多个断点,用info命令可以查看已经设置的断点:

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 a...done.
(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) b 7
Breakpoint 2 at 0x40053b: file a.c, line 7.
(gdb) b 8
Note: breakpoint 2 also set at pc 0x40053b.
Breakpoint 3 at 0x40053b: file a.c, line 8.
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040053b in main at a.c:7
3       breakpoint     keep y   0x000000000040053b in main at a.c:8
(gdb) 

[5]delete

  每个断点都有一个编号(有的断点行数不一样,但地址却一样,有的地方不能够设置断点或者说与上一个设置的断点等效),可以用编号指定删除某个断点。

......
(gdb) b 7
Breakpoint 2 at 0x40053b: file a.c, line 7.
(gdb) b 8
Note: breakpoint 2 also set at pc 0x40053b.
Breakpoint 3 at 0x40053b: file a.c, line 8.
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040053b in main at a.c:7
3       breakpoint     keep y   0x000000000040053b in main at a.c:8
(gdb) delete 3
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040053b in main at a.c:7
(gdb) 

【C语言】调试工具GDB简述-LMLPHP

  有时候一个断点暂时不用可以禁用掉而不必删除,这样以后想用的时候可以直接启用,而不必重新从代码里找应该在哪一行设断点,这个过程用 disable 和 enable 来完成。

[6]条件断点 (break 和run

  gdb的断点功能非常灵活,还可以设置断点在满足某个条件时才激活,例如:

......
//先把其余的断点删掉。
(gdb) b 9 if a == 2
Breakpoint 5 at 0x400552: file a.c, line 9.
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
5       breakpoint     keep y   0x0000000000400552 in main at a.c:9
        stop only if a == 2
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/2/02/a 
a = 1, b = 1
[Inferior 1 (process 22968) exited normally]
(gdb) 

  r表示从头开始运行程序,在a==2的条件下中断才有效。a不等于2,所以中断无效。  

[7] gdb的观察点(watch 和c

  断点是当程序执行到某一代码行时中断,而观察点是当程序访问某个存储单元时中断,如果我们不知道某个存储单元是在哪里被改动的,这时候观察点尤其有用。

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 a...done.
(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) watch b
Hardware watchpoint 2: b
(gdb) c
Continuing.

Hardware watchpoint 2: b

Old value = 0
New value = 1
main () at a.c:8
8           printf("a = %d, b = %d\n", a, b);
(gdb) 

【C语言】调试工具GDB简述-LMLPHP

  程序执行到b存储单元,将此执行单元执行前后的值都显示出来。

[8] 段错误

  如果程序运行时出现段错误,用gdb可以很容易定位到究竟是哪一行引发的段错误。在gdb中运行,遇到段错误会自动停下来,这时可以用命令查看当前执行到哪一行代码了。

  gdb显示段错误出现在 _IO_vfscanf 函数中,用bt命令可以看到是哪一个函数调用了它。

四、gdb基本命令

  gdb有许多有用的命令如list(显示源代码),这样就可以结合源码与调试信息更好的进行调试。将gdb常用命令摘抄如下表:

 

04-22 13:20