在linux系统下的GDB的调试,这是我调试的代码,方便学习。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
while(1){
char buff[128]={0};
printf("请输入数据:");
fgets(buff,128,stdin);
if(strcmp(buff,"end")==0){
break;
}
printf("buff=%s\n",buff);
}
}
生成编译文件
gcc -o main main.c -g
这里面,main是自定义下的编译后的名字添加-g是附带调试信息
查看调试代码
list,显示代码,可简写为l
一般是输入l 1,显示第一行代码也包括其他的代码
输入l 1,20,显示1到20行的代码
断点
设置断点
break 行号,简写b 行号,可设置多个断点
这里会发现,明明是13行,但是显示的是16行,这是因为 代码存在预处理(如宏展开、条件编译 ) ,预处理后实际编译的代码行号与原始代码行号有差异,GDB 依据编译后的代码定位断点,就会出现设置断点行(b 13
)和实际显示行(line 16
)不匹配的情况 。
当我们设置了多个断点的时候,发现自己忘记了,改如何调试呢,输入info break显示全部的断点信息。
删除断点
- delte ,简写为d,删除所有断点
- d 1,2 删除指定的断点,1,2是用info break显示断点的序号
在 GDB 里,断点序号是 全局递增、不会因删除而重置 的 。即便删除旧断点,新断点序号仍接着之前最大序号往后排,这是 GDB 设计逻辑,方便调试时追溯断点历史,所以删完再设新断点,序号从之前最大号(比如删完到 3、4,新断点就从 4、5 接着增 )延续,属于正常现象,不影响功能,想看当前有效断点用 i b
(info breakpoints )
禁用断点
disable表示禁用断点,disable 1,表示的是禁用的是第一个断点,不是第一行的断点
注意最开始和最前面的,状态时显示的,Enb n表示断点被禁用了
一次禁用多个断点,disable 1 2,和删除的原理差不多
启用断点
根据前面的,很显然,启用断点时enable,enable 1,同理,表示的是启用的是第一个断点,不是第一行的断点
一次启用用多个断点,enable 1 2,和删除的原理差不多
最后注意,删除,启用,禁用断点后面的数字是断点的序号,不是行号,使用info break查看,简写为i b,但是添加多个断点在这里面不行,要使用脚本,删除,启用,禁用多个断点是可以的
delete/disable/enable 断点序号
程序运行
启动
run,简写为r
这里是运行到断点处了
打印
我们要打印变量里面的数据,这要使用p打印,现在我要打印buff的值,p buff
这里发现是随机值,这是因为只是进度执行到这里了,但是这里还没有执行。就像计组里面cpu指令的寄存器,指向的是下一个将要执行的指令。
执行
单步执行
next,简写为n
可以看到,单步执行到第9行了。现在我要打印buff的值,p buff
可以看到现在数组里面全是0了。
进入函数与退出的操作
step,这里是进入函数内部。简写为s。之后在函数内部,c继续执行,finish是跳出函数。
结束调试
我一直执行下去,发现了问题
可以看到,如果字符是end,就结束输入,但是通过打印发现是end\n,多了一个换行符号。
这时,我们要退出调试,quit,简写为q。