GDB调试基础篇

目录

一、GDB的来源

二、GDB调试步骤

三、GDB调试基本命令

(1)GDB启动和退出

(2)运行命令

(3)设置断点

(4)打印/查看信息

四、总结

参考文献:


    在各种环境或系统中,为了能够帮助程序员更快的定位程序的出错原因,通常会有相应的调试器,调试器可以看作是程序员的小帮手了,比如:从事Android开发需要会使用Android Studio、从事Java开发需要会使用Eclipse、从事Linux操作系统开发需要会使用GDB等,调试工具是一把窥探程序内部秘密的钥匙!

   本文主要记录和总结在Linux环境下GDB调试使用到的基本步骤和命令。

一、GDB的来源

  先来认识一张GDB官方图标,是不是有点可爱:

                                                                                   

                                                                                    图1 GDB官方图标

  在编程过程中,经常听别人提起GDB、GDB调试、GDB乃程序员的基本素养、GDB从入门到放弃,那么什么是GDB呢?

    GDB即GNU调试器(GNU Debugger,简写GDB),是GNU软件系统中的标准调试器,目前主要应用于UNIX和类UNIX操作系统中。它的主要职责便是帮助程序员调试程序啦,俗称:“解BUG”。

   那GDB有哪些功能呢?

  • 启动你的程序,可以按照你自定义的要求随心所欲的运行程序;
  • 可以让被调试的程序在你所指定的断点处停住;
  • 当程序被停住时,可以检查此时你的程序中发生的事;
  • 你可以改变你的程序,将一个BUG修正,从而测试其他的BUG;

二、GDB调试步骤

一般在程序遇到问题时调试过程为:

  1. gdb <program> 开始调试程序;
  2. set args <args1 args2 ……argsn>设置程序需要的参数;
  3. break <condition> 设置断点;
  4. run 开始调试程序;
  5. next 执行下一步;
  6. quit 退出调试;

举个栗子:

有如下的程序,接下来的讲解也将使用程序 program.c 作为例子进行讲解(文件名:program.c):

#include <stdio.h>

void printStr(char str[])
{
    printf("%s\n", str);
}

int main(int argc,char *argv[])
{
    if (argc < 2) printf("Error: argc <= 2\n");
    printStr(argv[1]);

    int i = 0;
    int j = 1;
    int k = 2;

    int array[10];
    for (i = 0; i < 10; ++i) {
        array[i] = i;
    }

    printf("array : ");
    for (i = 0; i < 10; ++i) {
        printf("%d ", array[i]);
    }
    printf("\n");
}
[root@192 ~]# gcc -g program.c -o program
[root@192 ~]# gdb program
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/program...done.
(gdb) set args main
(gdb) quit
[root@192 ~]# gcc -g program.c -o program
[root@192 ~]# gdb program
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/program...done.
(gdb) set args this_is_program!
(gdb) break main
Breakpoint 1 at 0x4005d6: file program.c, line 10.
(gdb) run
Starting program: /root/program this_is_program!

Breakpoint 1, main (argc=2, argv=0x7fffffffe528) at program.c:10
10          if (argc < 2) printf("Error: argc <= 2\n");
Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64
(gdb) n
11          printStr(argv[1]);
(gdb) n
this_is_program!
13          int i = 0;
(gdb) quit
A debugging session is active.

        Inferior 1 [process 22607] will be killed.

Quit anyway? (y or n) y
[root@192 ~]#

上面是一个简单的调试过程,包括设置参数,设置断点,运行,其中,break,run 都可以采用简写b 以及 r来使用。

三、GDB调试基本命令

   GDB命令可以使用全称或简写(一般是首字母)执行;

(1)GDB启动和退出

  • gdb program : 启动调试;
  • quit : 简写q,退出调试,Ctrl+d也可以退出;  

  在编译的时候需要加上 -g 调试参数;

[root@192 ~]# gdb program
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/program...done.
(gdb) quit
[root@192 ~]#

(2)运行命令

  • run  : 简写 r,运行当前程序,遇到断点会停止,等待用户操作;
  • next : 简写 n, 单步执行程序,不进入函数内部;
  • step : 简写 s,单步执行程序,遇到函数会进入函数内部,注意与next命令区分;
  • continue : 简写 c,继续运行程序,直到遇到断点或程序结束;

例如:

[root@192 ~]# gdb program
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/program...done.
(gdb) set args this_is_program!
(gdb) b main
Breakpoint 1 at 0x4005d6: file program.c, line 10.
(gdb) b 22
Breakpoint 2 at 0x40062d: file program.c, line 22.
(gdb) r
Starting program: /root/program this_is_program!

Breakpoint 1, main (argc=2, argv=0x7fffffffe528) at program.c:10
10          if (argc < 2) printf("Error: argc <= 2\n");
Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64
(gdb) n
11          printStr(argv[1]);
(gdb) s
printStr (str=0x7fffffffe790 "this_is_program!") at program.c:5
5           printf("%s\n", str);
(gdb) n
this_is_program!
6       }
(gdb) continue
Continuing.

Breakpoint 2, main (argc=2, argv=0x7fffffffe528) at program.c:22
22          printf("array : ");
(gdb) n
23          for (i = 0; i < 10; ++i) {
(gdb) quit
A debugging session is active.

        Inferior 1 [process 22777] will be killed.

Quit anyway? (y or n) y
[root@192 ~]#

其中:

  • set args this_is_program! : 设置输入参数,可以设置多个;
  • b main : 设置函数断点;
  • b 22 : 设置行断点;
  • s : 进入printStr函数;
  • continue : 会在断点22行处停留,等待用户操作;

(3)设置断点

     设置和显示断点:

  • break <condition>: 简写 b,condition可以是函数名,程序行号,也可以是一个 表达式;
  • info breakpoints : 显示断点信息;

例如:

(gdb) set args this_is_program!
(gdb) b main
Breakpoint 1 at 0x4005d6: file program.c, line 10.
(gdb) b printStr
Breakpoint 2 at 0x4005b9: file program.c, line 5.
(gdb) b 22
Breakpoint 3 at 0x40062d: file program.c, line 22.
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005d6 in main at program.c:10
2       breakpoint     keep y   0x00000000004005b9 in printStr at program.c:5
3       breakpoint     keep y   0x000000000040062d in main at program.c:22
(gdb)

分别设置了函数和行断点,其中info breakpoints的显示信息中:

  • Num : 断点编号;
  • Type : 类型;
  • Disp : 断点执行一次之后是否有效,keep有效,dis无效;
  • Enb : 当前断点是否有效,y有效,n无效;
  • Address : 内存地址;
  • What : 断点位置;

   删除断点:

  • delete Num :  删除断点号为 Num的断点;
  • disable Num : 暂停断点号为Num的断点;
  • enable Num : 开启断点号为Num的断点;
  • delete breakpoints : 删除所有断点;

例如:

(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005d6 in main at program.c:10
2       breakpoint     keep y   0x00000000004005b9 in printStr at program.c:5
3       breakpoint     keep y   0x000000000040062d in main at program.c:22
(gdb) disable 1
(gdb) info breakpoints 1
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x00000000004005d6 in main at program.c:10
(gdb) enable 1
(gdb) info breakpoints 1
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005d6 in main at program.c:10
(gdb) delete 1
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x00000000004005b9 in printStr at program.c:5
3       breakpoint     keep y   0x000000000040062d in main at program.c:22
(gdb) delete breakpoints
Delete all breakpoints? (y or n) y
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb)

(4)打印/查看信息

  • print <condition>: 简写 p,打印condition值,condition可以是一个变量/函数调用/表达式等;
  • whatis <valueName>: 查看变量valueName类型;
  • list : 简写 l,查看代码,默认以当前行为中心查看10行;

例如(代码中多数使用简写):

(gdb) n
11          printStr(argv[1]);
(gdb)
this_is_program!
13          int i = 0;
(gdb)
14          int j = 1;
(gdb)
15          int k = 2;
(gdb) p i
$3 = 0
(gdb) p j
$4 = 1
(gdb) whatis i
type = int
(gdb) l
10          if (argc < 2) printf("Error: argc <= 2\n");
11          printStr(argv[1]);
12
13          int i = 0;
14          int j = 1;
15          int k = 2;
16
17          int array[10];
18          for (i = 0; i < 10; ++i) {
19              array[i] = i;
(gdb)

(5)设置信息

  • set <args args1 args2……> : 设置运行参数;
  • set var <valueName=value> : 设置/修改变量值;

例如(例子中命令多数使用了简写):

(gdb) set args this_is_program!
(gdb) b main
Breakpoint 1 at 0x4005d6: file program.c, line 10.
(gdb) r
Starting program: /root/program this_is_program!

Breakpoint 1, main (argc=2, argv=0x7fffffffe528) at program.c:10
10          if (argc < 2) printf("Error: argc <= 2\n");
Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64
(gdb) n
11          printStr(argv[1]);
(gdb) n
this_is_program!
13          int i = 0;
(gdb) n
14          int j = 1;
(gdb) p i
$1 = 0
(gdb) set var i=10
(gdb) p i
$2 = 10
(gdb)

四、总结

    本文只是对GDB的来源、功能、基本命令以及使用方法进行了介绍,当然还有更多更深入的功能,接下来的文章会进一步介绍。

参考文献:

[1] http://www.gnu.org/software/gdb/ (gdb 官方网站)

[2] https://download.csdn.net/download/u011074149/12553017 (gdb 使用手册)

[3] https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html

[4] https://blog.csdn.net/niyaozuozuihao/article/details/91802994

猜你喜欢

转载自blog.csdn.net/u011074149/article/details/106910296