Linux:调试器 - gdb

简介: Linux:调试器 - gdb

gbd基本概念

GDB (GNU Debugger) 是一个强大的命令行调试工具,用于调试各种编程语言(如C、C++、Java、Python等)编写的程序。使用 gdb可以帮助开发人员更快地定位和修复程序中的缺陷,提高代码质量和开发效率。它是 Linux/Unix 系统上最常用的调试工具之一。

先在Linux主机上安装gdb

yum install -y gdb

该指令需要root权限,要么sudo进行提权,要么以root身份执行。

如果一个可执行程序想要被gdb调试,那么该可执行程序必须带有调试信息,也就是以debug形式发布。我们现在有一个test.c源文件:

如果直接使用gcc那么其编译出来就是release版本:

gcc -o test-r test.c

带上-g选项后,gcc会以debug形式编译:

gcc -g -o test-d test.c

可以看到的是,debug版本的可执行程序test-d明显比release版本的大。我们可以通过readelf指令来查看可执行文件中有没有调试信息,可执行文件也是有固定格式的,这个格式叫做ELF,而readelf指令就是用于查看可执行文件内部内容的

先查看release版本的文件:

readelf -S test-r | grep debug

以上指令,管道左侧用于输出可执行文件内的内容,右侧用于筛选含debug的字段,最后该指令什么也没有输出,说明release版本内部不存在debug信息,也就是调试信息

再查看debug版本的文件:

readelf -S test-d | grep debug

输出结果如下:

可见该文件内部确实有debug调试信息。

随后我们就可以直接用gdb来调试可执行程序了:

gdb test-d

当看到以下页面,说明成功开始调试了:

如果想退出,输入q或者ctrl + d


gbd调试

我以以下代码为例,来进行调试示范:

#include <stdio.h>

int getNum(int n)
{
    int sum = 0;

    int j;
    for(j = 1; j <= n; j++)
    {
        sum += j;
    }

    return sum;
}

int main()
{
    int i, num = 0;

    for(i = 0; i < 10; i++)
    {
        num += getNum(i);
    }

    printf("%d\n", num);

    return 0;                                                                                           
}

浏览

l #:列出以#行为中心的10行代码

l:从上一次的最后一行开始,列出往后的10行代码

此处的l也可以改为list

第一次执行l 1,就会列出从第1行开始的代码:

再次输入l,则会从上一次的后一行代码开始,也就是第11行开始:

输入l 16

其不是从第16行开始,而是把第16行放在最中间,之前l 1从第一行开始,是因为第一行上面没有代码了。

l 函数名:列出某个函数的源代码

比如l main,就是列出main函数的代码:

不过其不是把main放在第一行,而是把main放在中心。


断点

b #:在行号为#处设置一个断点、

b 函数名:在函数的开头设置一个断点

bbreak的简写,此处的b改为break也可以。

现在我们要在第22行设置断点,输入b 22

其显示我们把断点设置在了第22行,断点序号为1

再给getNum函数设置一个断点,b getNum

其显示我们把断点设置在了第5行,断点序号为2

如果想查看我们设置过的断点:

info b:查看断点信息

此时就列出了目前所有的断点信息,Num表示断点编号;Enb表示当前断点是否生效;What描述了该断点的信息。

d #:删除编号为#的断点

此处ddelete的缩写,把d换为delete也可以。

使用d 2,把编号为2的断点删掉:

此时再info b,就只剩下编号为1的断点了。

disable #:禁用编号为#的断点

使用disable 1,把1号断点禁止:

再次info b,可以看到一号断点的Enb属性变为n了,表示该断点失效了。

enable #:启用编号为#的断点

使用enable 1,把1号断点启用:

再次info b,可以看到一号断点的Enb属性变为y了,表示该断点启用了。

总结一下断点相关命令:

命令 功能
b # 在行号为#处设置一个断点
b 函数名 在函数的开头设置一个断点
info b 查看断点信息
d # 删除编号为#的断点
disable # 禁用编号为#的断点
enable # 启用编号为#的断点

运行

r:运行程序

此处rrun的简写,使用run也可以

对当前程序使用r后,直接执行到了结尾,并输出结果165exit normally表示程序正常退出。

现在我们使用b getNumgetNum函数上打一个断点,再次执行r指令:

可以看到,此时没有直接执行完程序,而是执行到断点处就停止了。我们再执行一次r


其发出询问:"是否要从头开始执行",也就是说第一次使用r指令,会执行到下一个断点,如果没有断点就执行到程序结束,但是每次使用r都必须是从头开始执行的。因此r指令一般用于进入程序,后续的调试一般不用r

c:执行到下一个断点

此处的ccontinue的缩写,使用continue也可以。

对刚刚的程序执行c

第一次执行r指令,到达第一个断点,也就是第一次调用getNum的时候,此时参数n = 0。第二次执行c指令,到达下一个断点,第二次调用getNum此时参数n = 1。因此c用于断点之间的跳转。

n:逐过程调试

现在我们删除原先的getNum断点,把断点打在第22行:

也就是语句num += getNum(i);处。

对该程序多次使用n

第一次执行n,停在了for循环的语句;第二次执行n,停在了num += getNum(i);;第三次执行n,停在了for循环的语句。

逐过程调试的特点在于不会进入函数内部,把函数当成一个语句执行

s:逐语句调试

示例:

一开始我们处于num += getNum(i);中,此时执行s指令,其直接跳转到了getNum函数的内部,到达其第一条语句int sum = 0;

逐语句调试的特点在于会进入函数内部,详细展示函数内部的执行细节

finish:执行到当前函数返回

示例:

一开始我们处于getNum函数的第一条语句int sum = 0;处,此时直接执行finish指令,跳转到了函数结束,并告知本次调用函数返回值为6

总结:

命令 功能
r 运行程序
c 执行到下一个断点
n 逐过程调试
s 逐语句调试
finish 执行到当前函数返回

变量

我们也可以在gdb中随时查看变量的值。

p #:输出变量值

示例:

现在处于某一次调用getNum的过程中,使用p sum得到当前sum = 15p j得到当前j = 5p n得到当前n = 8

display #:跟踪名为#的变量,每次调试都会输出该变量的值

示例:

先跟踪nsumj三个变量:

支持c进行调试:

可以看到,其附带输出了nsumj的值。

每个变量前面都要一个数字,这是每个变量的编号。

undisplay #:取消对编号为#的变量的跟踪

示例:

一开始跟踪了nsumj三个变量,此时执行指令undisplay 2,就取消跟踪了sum变量。再次调试时,就没有sum变量了。

总结:

命令 功能
p # 输出变量值
display # 跟踪一个变量,每次调试都会输出该变量的值
undisplay # 取消对变量的跟踪

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
5天前
|
NoSQL Linux 编译器
【Linux】开始使用gdb吧!
这篇文章我们来学习 gdb 的使用方法。我们在Windows端编写代码时有宇宙最强编译器VS2022帮助我们调试,那Linux端有没有一款强大的调试工具呢???
52 17
【Linux】开始使用gdb吧!
|
5天前
|
NoSQL Linux C语言
【Linux】Linux调试器-gdb使用
【Linux】Linux调试器-gdb使用
8 0
|
5天前
|
NoSQL IDE Linux
Linux的学习之路:8、Linux调试器-gdb使用
Linux的学习之路:8、Linux调试器-gdb使用
21 0
|
5天前
|
安全 网络协议 Linux
linux必学的60个命令
Linux是一个功能强大的操作系统,提供了许多常用的命令行工具,用于管理文件、目录、进程、网络和系统配置等。以下是Linux必学的60个命令的概览,但请注意,这里可能无法列出所有命令的完整语法和选项,仅作为参考
263 2
|
1天前
|
安全 网络协议 Linux
linux必学的60个命令
Linux是强大操作系统,提供众多命令行工具,如安装登录(login, shutdown, install)、文件处理(file, mkdir, grep)和系统管理(df, top, kill)。此外,还包括网络操作(ifconfig, ping, telnet)和安全相关(passwd, su, chmod)命令。了解这些基础命令对于有效管理Linux系统至关重要。详细信息和特定用法可能因版本差异而变化,建议查阅相关文档。
|
2天前
|
NoSQL Linux Shell
Linux MongoDB重启命令
【5月更文挑战第8天】
|
3天前
|
存储 Linux Shell
YUM管理器的命令列表-Linux
YUM管理器的命令列表-Linux
11 0
|
5天前
|
Linux 程序员 计算机视觉
【linux 学习】在Linux中经常用到的cmake、make、make install等命令解析
【linux 学习】在Linux中经常用到的cmake、make、make install等命令解析
16 0
|
5天前
|
Linux
Linux的find命令使用
【5月更文挑战第11天】Linux的find命令使用
18 3