当代码出现bug时,你还在用printf大法吗?或者是手动模拟吗?尝试一下使用gdb调试器吧。
环境:vscode+linux
注意:gdb的调试对象是可执行文件,不是源文件。
假设有一个测试程序gdb.test.c
#include<stdio.h>
int get_sum(int n)
{
int sum=0,i;
for(i=0;i<n;i++)
sum+=i;
return sum;
}
int main()
{
int i=100,result;
result=get_sum(i);
printf("1+2+...+%d=%d\n",i,result);
return 0;
}
编译该程序
gcc -g gdb.test.c -o gdb.test
运行
./gdb.test
调试的命令格式
gdb gdb.test
//或者
gdb -q
(gdb) file test
输入quit退出gdb调试器
显示和查找程序源码
list命令:
list //显示接下来的10行代码
list 5,10 //显示第5行到第10行的代码
list gdb.test.c:5,10 //显示源文件gdb.test.c中的5到10行代码,在调试含多个源文件的程序时使用
list get_sum //显示get_sum函数周围的代码
list gdb.test.c:get_sum //显示源文件gdb.test.c中get_sum函数周围的代码,
//在调试含多个源文件的程序时使用
若在调试中运行Linux命令,需要在gdb的提示符下输入shell命令,例如:
(gdb) shell ls
执行程序和获得帮助
使用gdb -q filename 或 file filename 时,只是装入程序,并没有运行。在gdb提示符下输入run才可运行程序。
若要了解某个命令的使用方法:
(gdb) help list //了解list命令
(gdb) help all //列出所有gdb命令的帮助信息
设置和管理断点
设置断点:
(gdb) break 7 //以行号设置断点
(gdb) break get_sum //以函数名get_sum设置断点
(gdb) break 行号或函数名 if 条件 //以条件表达式设置断点
(gdb) watch 条件表达式 //以条件表达式设置断点的另一种方法
查看当前设置的断点:
使用info breakpoints命令
使中断失效或有效:
disable 断点编号 ------->使某个断点失效
enable 断点编号 ------->使某个断点恢复有效
删除断点:
clear: 删除程序中所有断点
clear 行号:删除此行的断点
clear 函数名:删除该函数的断点
delete 断点编号:删除指定编号的断点,若删除多个断点,断点编号用空格隔开
查看和设置变量的值
print命令:
print 变量或表达式 //打印变量或表达式当前的值
print 变量=值 //对变量进行赋值
print 表达式@要打印的值的个数n //打印以表达式值开始的n个数
whatis命令:
whatis 变量或表达式
显示某个变量或表达式值的数据类型
set命令:
set variable 变量=值 //给变量赋值的另一种方法
控制程序的执行
continue命令:
让程序继续运行,直到下一个断点或运行完为止
(gdb) continue
kill命令:
用于结束当前程序的调试
next和step命令:
相同点:一次一条语句执行该段代码。
区别:next将函数调用当作一条语句来执行,step会跟踪进入函数内部,一次一条执行函数内代码,直到执行完,才执行函数调用后的语句。
(gdb) next
(gdb) step
nexti和stepi命令:
和next以及step的用法相同,但是以机器指令为执行单位去执行。一条语句一般由多个机器指令组成。
以上便是常用的调试命令,若对不常用的命令有需求,可以用help all解决。