文章目录
使用GCC与GDB对c语言程序进行调试
1. 使用 GCC 编译代码时添加调试信息
在使用 GCC 编译源代码时添加 -g
选项,这会让编译器在生成的可执行文件中包含丰富的调试信息,例如源代码行号、变量名、函数名等,帮助 GDB 建立源代码和机器代码之间的映射关系。
示例代码(test.c
)
#include <stdio.h>
int add(int a, int b) {
int result = a + b;
return result;
}
int main() {
int num1 = 5;
int num2 = 10;
int sum = add(num1, num2);
printf("The sum is: %d\n", sum);
return 0;
}
编译命令
gcc -g -o test test.c
❯ gcc -g -o test test.c
❯ ls
test test.c
这里 -g
用于生成调试信息,-o test
指定生成的可执行文件名为 test
,test.c
是源代码文件。
2. 启动 GDB 调试器
编译完成后,使用 gdb
命令启动调试器并加载可执行文件。
gdb test
启动 GDB 后,会显示 GDB 的版本信息和一些提示信息,进入 GDB 的命令行交互界面,提示符为 (gdb)
。
还可以使用-tui
参数进入图形调试界面
gdb -tui test
3. 在 GDB 中进行调试操作
3.1 设置断点
断点可以让程序在指定位置暂停执行,方便你检查程序状态。
- 在指定行号设置断点:使用
break
或b
命令,后面跟上文件名和行号。例如,在test.c
文件的第 4 行设置断点:
(gdb) break test.c:4
- 在函数入口设置断点:直接使用函数名。例如,在
add
函数入口设置断点:
(gdb) break add
- 条件断点:可以为断点添加条件,只有当条件满足时,程序才会在该断点处暂停。例如,在
add
函数中,当a
等于 10 时设置断点:
(gdb) break add if a == 10
- 临时断点:使用
tbreak
命令设置的断点只生效一次,程序在该断点处暂停一次后,该断点会自动删除。例如:
(gdb) tbreak main
3.2 查看断点信息
使用 info breakpoints
或 info b
命令可以查看当前设置的所有断点信息,包括断点编号、位置、是否启用、命中次数等。
(gdb) info breakpoints
3.3 启用和禁用断点
- 禁用断点:使用
disable
命令后面跟上断点编号,可以暂时禁用指定的断点。例如,禁用断点 1:
(gdb) disable 1
- 启用断点:使用
enable
命令后面跟上断点编号,可以重新启用被禁用的断点。例如,启用断点 1:
(gdb) enable 1
3.4 删除断点
使用 delete
命令后面跟上断点编号,可以删除指定的断点。例如,删除断点 1:
(gdb) delete 1
将1,2断点删除后,3,4断点序号不变
3.5 运行程序
使用 run
或 r
命令开始运行程序,程序会在遇到断点时暂停。
(gdb) run
如果程序运行时需要传递命令行参数,可以在 run
命令后面跟上参数。例如:
(gdb) run arg1 arg2
3.6 单步执行
- 逐行执行(不进入函数内部):使用
next
或n
命令,每次执行一行代码,如果遇到函数调用,会将函数调用作为一行代码执行完。
(gdb) next
当前断点设置在第10行
在执行了两步n
之后并没有进入add
函数进行逐行调试,而是在main
函数中逐行调试
- 逐行执行(进入函数内部):使用
step
或s
命令,当遇到函数调用时,会进入函数内部逐行执行。
(gdb) step
现在断点同样设置在第十行
在执行了两步之后进入了add
函数继续执行
- 跳出当前函数:使用
finish
命令,程序会继续执行直到当前函数返回,并显示函数的返回值。
(gdb) finish
在add
函数中执行finish
命令跳出了add
函数,进入了main
函数
3.7 查看变量值
使用 print
或 p
命令查看变量的当前值。
- 查看普通变量:例如,查看变量
num1
的值:
(gdb) print num1
- 查看数组元素:假设
arr
是一个数组,查看数组的第一个元素:
(gdb) print arr[0]
- 查看指针指向的值:假设
ptr
是一个指针,查看指针指向的值:
(gdb) print *ptr
- 格式化输出:可以使用
print
命令的格式化选项来指定输出格式。例如,以十六进制格式输出变量num1
的值:
(gdb) print/x num1
- 查看当前局部变量的值:
(gdb) info locals
3.8 查看源代码
- 显示当前行附近的源代码:使用
list
或l
命令可以显示当前执行位置附近的源代码。默认显示 10 行,可以通过设置listsize
变量来改变显示的行数。
(gdb) list
- 显示指定行附近的源代码:可以在
list
命令后面跟上行号。例如,显示test.c
文件第 5 行附近的源代码:
(gdb) list test.c:5
3.9 查看调用栈
使用 backtrace
或 bt
命令查看函数调用栈,了解程序的执行流程和函数调用关系。
(gdb) backtrace
可以使用 frame
命令后面跟上栈帧编号,切换到指定的栈帧,查看该栈帧中的变量和执行位置。例如,切换到栈帧 1:
(gdb) frame 1
3.10 继续执行程序
使用 continue
或 c
命令让程序从当前断点继续执行,直到遇到下一个断点或程序结束。
(gdb) continue
3.11 查看寄存器值
使用 info registers
命令可以查看当前寄存器的值。
(gdb) info registers
3.12 退出 GDB
使用 quit
或 q
命令退出 GDB 调试器。
(gdb) quit
示例调试流程
# 编译代码并添加调试信息
gcc -g -o test test.c
# 启动 GDB 并加载可执行文件
gdb -tui test
# 在 add 函数入口设置断点
(gdb) break add
# 运行程序
(gdb) run
# 进入函数内部单步执行
(gdb) step
# 查看变量值
(gdb) print a
(gdb) print b
# 继续执行到函数返回
(gdb) finish
# 查看调用栈
(gdb) backtrace
# 退出 GDB
(gdb) quit
通过以上详细的步骤和命令,你可以使用 GCC 和 GDB 对 C 程序进行全面而深入的调试。