GDB的使用

目录

1. 什么是gdb

2. gdb的使用

2.1 生成调试信息

2.2 gdb的基本用法

2.2.1 启动gdb

2.2.2 gdb退出

2.2.3 列出源码

2.2.4 运行程序

2.2.5 断点

2.2.6 逐过程调试和单步调试 

2.2.7 显示变量的值

2.2.8 修改变量的值 

2.2.9 跳转到指定的行

2.2.10 跳到下一个断点


1. 什么是gdb

gdb是一个调试器,能够帮助开发人员诊断和修复程序中的错误

gdb可以在程序运行时暂停程序并检查程序状态,例如检查变量的值、执行栈跟踪和查看内存内容,并且gdb支持多种编程语言,包括C、C ++、Objective-C、Fortran和Ada等。gdb也可以在终端命令行中使用,也可以与多种集成开发环境(IDE)集成使用。gdb是一个强大而灵活的工具,可用于调试各种类型的程序,从简单的命令行应用程序到复杂的多线程网络应用程序都能够通过gdb调试

gdb具有如下优点:

  1. 能够在程序运行时暂停,检查程序状态,有助于诊断和修复程序中的错误
  2. 支持多种编程语言,包括C、C ++、Objective-C、Fortran和Ada等
  3. 具有强大的功能,如检查变量的值、执行栈跟踪和查看内存内容等
  4. 可以与多种集成开发环境(IDE)集成使用,提高开发效率
  5. gdb是开源软件,可以在多个平台上免费使用
  6. gdb支持远程调试,可以在远程计算机上调试程序
  7. gdb具有良好的文档和社区支持,有很多的教程和示例可供参考

报错解决:

如果在后续使用gdb时出现如下报错

Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64

解决方法如下:

  1. sudo vim /etc/yum.repos.d/CentOS-Debuginfo.repo 
  2. 将下面内容粘贴进去
    [base-debuginfo]
    name=CentOS-$releasever - DebugInfo
    baseurl=http://debuginfo.centos.org/$releasever/$basearch/
    gpgcheck=0
    enabled=0
    protect=1
    priority=1
  3. enabled=0 改成 enabled=1 保存退出
  4. sudo yum install glibc yum-utils
  5. debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64
  6. 问题解决

2. gdb的使用

2.1 生成调试信息

Linux下的ELF可执行目标文件由一系列的section组成,其中有一个section为.debug,.debug节通常是一些调试工具(如gdb)使用的关键节之一,它们可以解析这些信息以提供调试信息和帮助调试程序

GDB的使用_第1张图片

在Linux下,程序的发布方式有两种,debug模式和release模式,通过gcc/g++编译形成的可执行文件默认是release模式的,也就是说不能够进行调试,因此要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项,才会在生成的可执行目标文件中带上.debug节

对于已经生成的源文件,可以通过下面的命令查看目标文件中的信息

readelf -S [filename] | grep -i debug
// readelf 用于读取和显示 ELF (Executable and Linkable Format) 文件信息
// -S 显示 ELF 文件的所有节(section)的信息

// grep -i 选项表示忽略大小写

以下面的test.c文件为示例

#include 

// 求 0-n 的和
int AddToN(int n)
{
    int res = 0;
    for (int i = 0; i <= n; i++)
    {
        res += i;
    }

    return res;
}

int main()
{
    int n, res;
    scanf("%d", &n);
    res = AddToN(n);

    printf("res: %d\n", res);
    return 0;
}

gcc test.c -o test 生成 test文件,readelf后发现没有用于调试的.debug section

GDB的使用_第2张图片

接下来在编译时带上 -g 选项,会发现生成的test.debug文件大小明显更大

GDB的使用_第3张图片

GDB的使用_第4张图片

这些内容就是调试信息,因此在使用gdb进行调试前,一定要确保在编译时带上 -g 选项  

2.2 gdb的基本用法

gdb可以在终端命令行中使用,也可以与多种集成开发环境(IDE)集成使用,这里只介绍在命令行中的基本使用

2.2.1 启动gdb

直接在命令行上输入gdb,后面接上要调试的文件名即可 

gdb binFile

GDB的使用_第5张图片

启动gdb成功之后,最后一行信息显示如下,说明调试信息读取成功,可以进行调试 

Reading symbols from /home/hqs/code/April/3/test.debug...done.

2.2.2 gdb退出

ctrl + d 或 输入 quit 后按回车

GDB的使用_第6张图片

2.2.3 列出源码

list 列出当前文件的源代码,默认列出前10行 (list 可以简写为 l)

选项
list [n], +:从指定行号n开始,列出该行后面的源代码
list [function_name]:列出指定函数的源代码
list [sline], [eline]:列出指定行号范围内的源代码,比如list 10 20 显示10-20行之间的代码
list -:列出上一个list命令列出的源代码的下一部分
list +:列出当前行后面的源代码

如果想要从第一行开始打印,可以使用以下命令,一次默认打印10行

list 1

如果要继续往后看,可以使用 list + 命令或者直接按回车,因为gdb会记住你上一次的操作,当你没有输入时按回车,gdb就重复你上一次的操作,这里就是list,会自动将后10行的内容显示出来

GDB的使用_第7张图片

查看第n行的源代码可以用下面的命令,gdb会以n为中心,显示出前5行和后4行代码,共计10行

list n

GDB的使用_第8张图片

2.2.4 运行程序

要运行程序,直接输入run即可,程序会一直运行到断点处停下来,如果没有断点则直接运行结束

run (简写为 r)

GDB的使用_第9张图片

还有另外一组命令可以在gdb中运行程序 

start:启动程序并停在程序的入口处
continue:继续运行程序

GDB的使用_第10张图片

2.2.5 断点

 新增断点

直接run会运行到程序退出不方便调试,为了利于调试和观察我们需要在程序的某些地方加上断点,好让程序在一个便于观察的地方停下来,使用的命令如下linenum是要设置断点的行号

break linemun (break简写为 b)
b 10 就是在第10行设置一个断点

设置好断点后可以查看已经设置的断点,命令如下

info break (简写为 info b)

GDB的使用_第11张图片

 删除断点

delete n (delete简写为 d,n表示断点编号,因此通常配合info来使用)
d 2 表示删除第二个断点

在打断点时,gdb会默认给每一个断点一个编号,因此在删除断点的时候,只能根据编号删除

GDB的使用_第12张图片

 打开和关闭断点

disable breakpoint_number (breakpoint_number 是要关闭的断点编号)
enable breakpoint_number  (breakpoint_number 是要打开的断点编号)

关闭断点不等于删除断点,它跟类似于将这个断点暂时禁用,以后有需要可以随时打开它,所以在info b时还能够看到这个断点存在的信息,之不过其Enb字段由 y(yes) 变成了 n(no) 

GDB的使用_第13张图片

2.2.6 逐过程调试和单步调试 

在完成了断点的设置后,就可以让程序停在断点处,然后一步一步调试来观察程序,这里可以分为两种方式

逐过程

逐过程调试会执行下一行,当遇到函数调用时,会一次性执行完该函数,也就是说不会进到函数体内部,其命令为

next (简写为 n)

GDB的使用_第14张图片

这里将断点打在第19行,输入r运行,程序停在第19行,按下n直接跳转到第20行 

单步调试(逐语句)

单步调试时同样会执行下一行,当遇到函数调用时,会进入改函数体内部,其命令为

step (简写为 s)

GDB的使用_第15张图片

GDB的使用_第16张图片

调用堆栈

在单步调试时,可以从一个函数体内部进到另一个函数体内部,此时我们所处的栈帧位置也发生了变化,如果需要查看堆栈信息,可以使用如下命令

backtrace (简写为 bt)

GDB的使用_第17张图片

GDB的使用_第18张图片

结束堆栈

当进入到另一个函数体之后,如果想跳出这个函数体回到调用的地方,使用如下命令

finish

GDB的使用_第19张图片

GDB的使用_第20张图片

2.2.7 显示变量的值

临时查看

当需要查看变量的值时,有如下一些做法

print (简写为 p)
  1. 在gdb中启动程序并进入调试模式

  2. 在程序执行到需要查看变量的位置时,可以使用break或b命令在该位置设置断点

  3. 使用run或r命令运行程序,程序将在断点处停止

  4. 使用print或p命令查看变量的值

查看变量:

print var_name    // var_name是要查看的变量名称

查看数组或结构体变量的值:

print *array@len   // 显示数组array的前len个元素的值
print struct_name  // 显示结构体struct_name的成员变量值

查看指针

print *pointer_name // 查看指针指向的值
print pointer_name  // 查看指针本身

GDB的使用_第21张图片

长显示

在调试程序时,经常需要反复查看某个变量的值,而不希望每次都输入一遍print命令。这时可以使用gdb的display命令,该命令会在每次程序停止时自动显示指定变量的值 

display

每指定一个变量,这个变量都会带上一个编号,如果要关闭某个变量的长显示,使用下面的命令

undisplay display_number (display_number是使用display命令时分配的编号)

GDB的使用_第22张图片

2.2.8 修改变量的值 

当需要对某个变量的值进行修改时,使用如下的命令

set variable_name = new_value 
比如 set i = 10 就是将变量i的值设为10

这里将 i 设为10, 下一步不满足循环条件,直接跳出循环

GDB的使用_第23张图片

2.2.9 跳转到指定的行

在调试程序时,有时候需要让程序执行到指定的代码行之前或之后停止,可以使用gdb的until命令

until line_number (line_number是要执行到的行号)
until 15 表示直接跳到15行执行(前面的执行流跑完)

GDB的使用_第24张图片

2.2.10 跳到下一个断点

在gdb中,c命令用于继续执行程序,直到下一个断点或程序结束。

continue (简写为 c)

具体操作步骤如下:

  1. 在gdb中启动程序并进入调试模式

  2. 使用break或b命令设置(多个)断点

  3. 使用run或r命令运行程序,程序将在第一个断点处停止

  4. 在停止时,可以使用print命令查看变量的值,使用step或s命令逐行执行程序,使用next或n命令跳过函数调用等

  5. 如果想要继续执行程序,可以使用c命令

GDB的使用_第25张图片

你可能感兴趣的:(linux,linux,服务器)