前言
以往我们使用VS这种IDE的时候,编代码和调试一体就非常方便。但来到了Linux我们的编辑器、编译器和调试器都是分开的。Linux上的调试工具就是gdb。
但是我们还需要清楚gcc默认编译的是release版本,该版本是不能调试的。还需要加上-g选项编译成debug版本
调试信息
为什么release版本不能调试而debug版本可以呢?本质因为debug版本多了一些调试信息。我们来简单看一下吧:
shell
[zhangwho@VM-0-2-centos lesson12]$ gcc -o code.exe code.c
[zhangwho@VM-0-2-centos lesson12]$ gcc -g -o code-debug.exe code.c
[zhangwho@VM-0-2-centos lesson12]$ ll
total 32
-rw-rw-r-- 1 zhangwho zhangwho 130 Dec 5 13:59 code.c
-rwxrwxr-x 1 zhangwho zhangwho 9368 Dec 5 14:05 code-debug.exe
-rwxrwxr-x 1 zhangwho zhangwho 8360 Dec 5 14:05 code.exe
-rw-rw-r-- 1 zhangwho zhangwho 70 Dec 5 13:58 makefile
很显然我们看到debug版本的就更大一点。
更直接地我们可以用readelf指令看看debug版本的调试信息:


gdb的使用
想使用gdb非常简单,直接gdb debug程序名即可:

不过我们并不能边看着代码边调试,这事挺烦的。但我们可以打印用选项打印出代码:

注意到代码不是从开头开始打印的,如果想要从开头开始打印。只需要list 行号/l 行号:

也可以像这样:

也能输入对应函数名:

注意到gdb查找时会显示上下文。
运行
那么怎么让程序运行呢?
只需输入run指令:

相当于vs的F5选项,直接运行到程序结束了。
断点
直接运行显然没有意义,我们可以用b+行号给对应行打上断点:

此时再r就会运行至断点处.
info b指令就可以查看已打断点信息:

同时我们可以用d+断点序号删除断点:

当然我们也可以禁用断点而非删除断点:

此时该断点的Enb状态就变成n了。
对应的,启用断点就是enale指令:

continue\c 指令可以从一个断点运行至下一个断点:

逐过程、逐语句、逐函数
输入next\n指令即可达到vs中f10的逐过程效果:

输入step\s指令即逐语句:

监视变量
我们使用vs调试功能中最常用的就是窗口监视变量。
使用print\p + 变量名即可输出目前变量值

同样可以查看变量地址:

当然我们可以用display+变量名指令让这些变量自动显示出来:

undisplay指令可以去掉常显示:

finish指令则可以直接运行至当前函数结束:

跳出循环
当我们运行至循环体的时候,逐步和逐语句都要执行很多次才能出循环,那么有没有一个指令可以直接跳出循环体呢?
有的兄弟,有的!
until+行号,直接执行至对应行:

退出
退出gdb只需输入q/quit指令即可
总结指令
- list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
- list/l 函数名:列出某个函数的源代码。
- r或run:运行程序。
- n 或 next:单条执行。
- s或step:进入函数调用
- break(b) 行号:在某一行设置断点
- break 函数名:在某个函数开头设置断点
- info break :查看断点信息。
- finish:执行到当前函数返回,然后挺下来等待命令
- print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
- p 变量:打印变量值。
- set var:修改变量的值
- continue(或c):从当前位置开始连续而非单步执行程序
- run(或r):从开始连续而非单步执行程序
- delete breakpoints:删除所有断点
- delete breakpoints n:删除序号为n的断点
- disable breakpoints:禁用断点
- enable breakpoints:启用断点
- info(或i) breakpoints:参看当前设置了哪些断点
- display 变量名:跟踪查看一个变量,每次停下来都显示它的值
- undisplay:取消对先前设置的那些变量的跟踪
- until X行号:跳至X行
- breaktrace(或bt):查看各级函数调用及参数
- info(i) locals:查看当前栈帧局部变量的值
- quit:退出gdb