🔥个人专栏:Linux—登神长阶
⛺️ 欢迎关注:👍点赞 👂🏽留言 😍收藏 💞 💞 💞
1. 引言📃
1.1 什么是GDB / CGDB?
🚀GDB(GNU Debugger)是 GNU 项目提供的一种调试工具,用于调试 C、C++ 和其他编程语言编写的程序。它允许程序员查看和控制程序的执行,从而帮助找到和修复程序中的错误。
🚀CGDB 是 GDB 的一个前端,它提供了一个更为用户友好的命令行界面,结合了文本用户界面(TUI)和普通的命令行。CGDB 提供了更加直观的视图和界面,使得调试过程更为高效。
1.2 两者各自的功能
【GDB 的主要功能】
- 启动程序:可以在 GDB 中启动程序,设置参数和环境变量。
- 设置断点:允许用户在程序中的特定位置设置断点,以便程序执行到该位置时暂停。
- 单步调试:可以逐行执行代码,观察每一步的行为和变量的变化。
- 查看和修改变量:可以查看程序中的变量值,也可以在调试过程中修改这些变量。
- 调用栈跟踪:可以查看当前的调用栈,帮助识别程序执行路径。
- 后退调试:支持在某些情况下“后退”执行,以帮助分析错误。
- 脚本和自动化:支持通过脚本进行自动化调试,便于重复调试相似的问题。
【CGDB 的主要功能】
- 图形化用户界面:提供了一个可视化的界面,使得调试过程更为直观。
- 命令窗口与文本窗口结合:可以在同一界面中查看代码和 GDB 命令的输出,提高调试效率。
- 多窗口支持:支持多个窗口,使得同时查看代码、变量和命令输出变得容易。
- 快捷键支持:提供了多种快捷键来快速执行常用操作,提升使用体验。
1.3 如何安装
-- 安装gdb/cgdb
sudo yum install -y gdb
sudo yum install -y cgdb
-- 检查是否安装成功
gdb --version
cgdb --version
2. GDB / CGDB 的使用
- 程序的发布方式有两种, debug 模式和 release 模式
- Linux gcc/g++ 出来的二进制程序,默认是 release 模式,不可调试
- 要使用 gdb / cgdb 调试,必须在源代码生成二进制程序的时候 , 加上 - g 选项
🥑 代码案例
下面是我们这次调式需要使用代码:
#include <stdio.h>
int flag = 0;
int sum(int s, int e){
int sum = 0;
int i = s;
for(; i <= e; i++) sum += i;
return sum * flag;
}
int div(int x, int y){
if(y == 0) return -1;
int z = x / y;
return z;
}
int main()
{
printf("process is running ");
int start = 1;
int end = 10;
int result = sum(start, end);
printf("process is done, result: %d\n",result);
int a = div(10, 0);
printf("process is done, result: %d\n",a);
return 0;
}
🥝 生成调试文件
不调试的情况下,使用 gcc 指令编译文件一般是:gcc test.c -o test 但是,如果要调试,那么就必须要加上 -g 指令。其原理用 Visual Studio Code 环境下来类比,使用该 IDE 熟悉的话便知道 发行一个程序的时候,可以有 release 版本和 debug 版本,只有我们选择 debug 版本的时候,程序才可以被调试,否则不行。这里也类似,加上 -g 就相当于生成 debug 版本的程序,不加就默认是 release 版本的。
方式一:
方式二:
🍊可以看到的是,debug
版本的可执行程序test.d
明显比release版本test.r的大。
方式三:
为了方便,我们还是把调式代码指令写到Makefile 文件中。上面的test.r 和 test.d 的调式版本只是给大家看一下,下面我们不做过多区分,统一用 test 可执行文件来替代。
test:test.c
gcc -o $@ $^ -g -std=c11
.PHONY:clean
clean:
rm -f test
🥑 readelf命令
🍊我们可以通过readelf
指令来查看可执行文件中有没有调试信息。
3. 调式指令📚
3.1 指令集
💢 gdb binFile 退出: ctrl + d 或 quit 调试命令:
指令名 | 作用 |
---|---|
l(list) 行号/函数名 | 显示对应的code,每次10行 |
r(run) | F5【无断点直接运行、有断点从第一个断点处开始运行】 |
b(breakpoint) + 行号 | 在哪一行打断点 |
b 源文件:函数名 | 在该函数的第一行打上断点 |
b 源文件:行号 | 在该源文件中的这行加上一个断点 |
info b | 查看断点的信息 |
breakpoint already hit 1 time | 【此断点被命中一次】 |
d(delete) + 当前要删除断点的编号 | 删除一个断点【不可以d + 行号】 |
若当前没有跳出过gdb | 则断点的编号会持续累加 |
d + breakpoints | 删除所有的断点 |
disable b(breakpoints) | 使所有断点无效【默认缺省】 |
enable b(breakpoints) | 使所有断点有效【默认缺省】 |
disable b(breakpoint) + 编号 | 使一个断点无效【禁用断点】 |
enable b(breakpoint) + 编号 | 使一个断点有效【开启断点】 |
enable breakpount | 使一个断点有效【开启断点】 |
n(next) | 逐过程【相当于F10】 |
s(step) | 逐语句【相当于F11】 |
bt | 看到底层函数调用的过程【函数压栈】 |
set var | 修改变量的值 |
p(print) 变量名 | 打印变量值 |
display | 跟踪查看一个变量,每次停下来都显示它的值【变量/结构体…】 |
undisplay + 变量名编号 | 取消对先前设置的那些变量的跟踪 |
until + 行号 | 进行指定位置跳转,执行完区间代码 |
finish | 在一个函数内部,执行到当前函数返回,然后停下来等待命令 |
c(continue) | 从一个断点处,直接运行至下一个断点处【VS下不断按F5】 |
3.2 案例演示
首先我们进入到 gdb / cgdb
,然后它会等待我们输入指令
cgdb test 或者 cgdb test
🍅l -- 行号显示
注:还可以查看指令文件,并且在输入指令之后,可以一直回车,就会显示该文件下的所有内容了
🍅 r -- 直接运行程序
🍅 增加/查看/删除断点
🍅 n/s -- 逐过程/逐语句
3.3 补充
watch(监视)
执行时监视一个表达式(如变量)的值,如果监视的表达式在程序运行期间的值发生变化,GDB 会暂停程序的执行,并且通知使用者
注:如果你有一些变量不应该修改,但是你怀疑它修改导致了问题,就可以 watch 它,如果发生了变化,就会通知你。
set var (确定问题原因)
更改一下标志位
条件断点
条件断点添加常见两种形式:1. 新增 2. 给已有断点追加
- 新增:b 行号/文件名:行号/函数名 if i == 30 (条件)
- 给已有断点追加:condition 2 i == 30, 其中 2 是已有断点编号,没有if
在此其他的指令我们就不过多讲解,大家可以看完文章后自行实践一下
4. 为什么要使用gdb / cgdb 来调试
1. 强大的调试功能
- GDB 功能强大:GDB 允许开发者进行单步调试、设置断点、观察变量的值、检查内存状态等。这些功能帮助开发者深入了解程序的执行流程,并迅速定位错误。
2. 支持多种编程语言
- 多语言支持:GDB 支持多种编程语言,包括 C、C++、Fortran、Go 等。这使得它成为跨语言开发的通用调试工具。
3. 适合命令行操作
- 命令行界面:在 Linux 环境中,命令行操作是常见的工作方式。GDB 提供了一个强大的命令行界面,使得高级用户可以通过命令快速高效地调试程序。
4. 与其他工具的集成
- 与其他开发工具集成:GDB 可以与许多其他开发工具和 IDE(集成开发环境)集成,例如 Eclipse、VSCode 等。这使得在开发过程中调试变得更加方便。
5. CGDB 提升用户体验
- CGDB 的图形化界面:CGDB 提供了一个基于终端的用户界面,可以在终端中以图形化的方式查看代码和调试信息。这对于喜欢在终端中工作的开发者来说,提供了更好的可视化体验,尤其是在处理大型代码时。
6. 实时调试
- 实时调试能力:GDB 支持对正在运行的程序进行调试,可以暂停程序的执行、检查状态并修改变量值,从而实时查看更改对程序行为的影响。
7. 追踪内存和资源问题
- 内存调试:GDB 可以帮助开发者追踪内存泄漏和未定义行为,这对于 C 和 C++ 等语言尤为重要,因为这些语言对内存管理的要求较高。
8. 开源与社区支持
- 开源和广泛社区支持:GDB 是开源的,拥有广泛的用户和开发者社区。用户可以获得丰富的文档、教程和支持,这对于解决问题和学习使用非常有帮助。
📖 总结
补充:当我们的 shell 光标消失了之后该咋办,如下:
输入 qui,然后光标就会恢复了
本文主要讲了关于 gdb / cgdb 是什么、怎么用、以及为什么要去使用两者来调试,对于上面的一些基础指令,大家还是要多去运用熟悉。
💞 💞 💞【*★,°*:.☆( ̄▽ ̄)/$:*.°★* 】那么本篇到此就结束啦,如果我的这篇博客可以给你提供有益的参考和启示,可以三连支持一下 !!