目录
一、概述
1.1 gdb是什么
1.2 为什么要使用gdb
二、gdb的简单使用
2.1 安装gdb
2.2 软件的debug版本和release版本
2.3 使用gdb
在之前的学习中,我们已经能够用vim编写和gcc/g++编译代码了,下面来学习如何调试代码。
一、概述
1.1 gdb是什么
在Linux系统中,GDB(GNU Debugger)是一个强大的、灵活的、开源的调试工具,用于对程序进行调试。它允许开发人员在程序崩溃或者运行出错时检查程序的内部状态,跟踪代码的执行过程,并尝试找出程序中的错误。
gdb是 GDB 命令行工具的缩写形式,可以在终端中使用该命令启动 GDB 调试器。
1.2 为什么要使用gdb
我们在编写代码时总会有各种各样的错误,这些错误基本可以分为两类:
- 语法错误:编译器会报错,解决比较方便
- 逻辑错误:此时就需要调试代码
虽然我们有各种各样的IDE,但是对于从事 Linux C/C++ 开发的程序员来说,大多数都需要熟悉gdb调试工具。尤其当不具备IDE的环境时(嵌入式系统等资源限制的场景),gdb以其占用资源少、开源免费和方便实用的优势被广泛使用。
二、gdb的简单使用
在Linux下调试代码分为两步:
- 调试代码的思路。
- 调试代码的工具。
确定问题、分析缩小范围、找到问题所在、提出解决方案。这种调试代码的思路都是一样的,所以调试代码侧重点在于把调试思路用在gdb这个调试工具上
2.1 安装gdb
- 打开终端并输入以下命令来安装gdb:
sudo yum install -y gdb
- 安装完成后,您可以使用以下命令来验证gdb是否成功安装:
gdb --version
2.2 软件的debug版本和release版本
程序的发布方式有两种,debug模式和release模式,debug模式可以被调试,release版本用于测试和发布。
原因:测试人员要测试的代码,必须是用户最终用的,debug版本有很多调试信息,这些信息用户不需要而且也会使软件资源占用较大。release版本的代码都是用户需要的。
使用 gdb <可执行程序名> 即可进入调试模式,
但要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项,否则报错。
Linux gcc/g++出来的二进制程序,默认是release模式。
证明:1.在debug发布的时候,一定要给可执行程序内部添加debug信息,否则无法调试!
2.release文件更小
我们在Linux中形成的可执行程序格式:ELF格式 ,包含很多可执行程序的信息,如代码开始和结束的位置,用以下命令读取。
readelf -S <可执行程序名> -g | grep -i debug
-S 读取二进制文件构成, -i 忽略大小写
执行readelf -S <可执行程序名> -r | grep -i debug 不会显示信息,因为没有release版本没有调试信息。
结论:如果你想让你的程序被调试,必须加 -g 以debug方式发布!
2.3 使用gdb
使用 gdb <可执行程序名> 即可进入调试模式,q 退出
常用的 gdb 命令:
- list(l) 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
- list(l) 函数名:列出某个函数的源代码。
- run(r):运行程序。
类似vs的F5,没有断点是直接运行。 - next(n):单条执行。
类似Vs的F10 - step(s):进入函数调用
类似Vs的F11 - break(b) 行号:在某一行设置断点
b 18 给当前文件18行打断点
b mycode.c:20 在mycode.c的第20行打断点 - break(b) 函数名:在某个函数开头设置断点
b main 在main函数的入口处打断点
b mycode.c:ADD 在mycode.c的ADD函数的入口处打断点 - info(i) break(b) :查看断点信息。
Enb:使能,即断点有没有开启/生效 - finish:执行到当前函数返回,然后挺下来等待命令
运行一个函数至函数完成 - print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
print(x+1) 将输出 x+1 表达式的计算结果。 - p 变量:打印变量值。
p x 将输出变量 x 当前的值 - set var:修改变量的值
不是一直执行到变量为该值,而是直接修改变量,最终结果可能不符合期望,例如累加。
常用于条件判断 - continue(或c):从当前位置开始连续而非单步执行程序
从一个断点运行到下一个断点处 - run(或r):从开始连续而非单步执行程序
- delete breakpoints:删除所有断点
- delete breakpoints n:删除序号为n的断点
- disable breakpoints:禁用断点
断点存在,但是不起作用 - enable breakpoints:启用断点
与 disable 相反,该命令将启用当前所有被禁用的断点,使它们重新生效。 - display 变量名(或变量的地址):跟踪查看一个变量,每次停下来都显示它的值
长显示一个变量,并带上编号,从下往上递增 - undisplay n:取消对先前设置的序号为n的变量的跟踪
取消长显示,序号递增不会重复 - until X行号:跳至X行
如果目的行不是有效代码( '{' '}' 或空格 ),将会跳到下一个有效代码的位置。
不用打断点就可以跳到指定行,常用于循环。 - breaktrace(或bt):查看各级函数调用及参数
查看调用堆栈 - info(i) locals:查看当前栈帧局部变量的值
- quit:退出gdb
注:
- list可简写成 l ,break 可简写成 b ,print 可简写成(p),continue 可简写成 c ,
run可简写成 r ,info 可简写成 i ,quit 可简写成 q - gdb会记录最近执行的命令,按回车键可执行上一次的命令。
例如输入 l 后,按回车键直接继续向下展开代码,直至结束,不用再输入“l 行号”。 - gdb文件可以根据文件的行号、文件名打断点,但是删除断点时不能使用行号或函数名,只能根据断点编号删除(使用info b查看)
- 在一个调试周期中,断点的编号是一直递增的,一个编号只会出现一次,退出gdb模式时,所有的断点信息被清空
以上所讲都是常用命令,希望大家能够熟练使用,也希望大家能在网上搜索和学习gdb的其他使用方法。