GDB
1.什么是GDB
GDB 是由 GNU 软件系统社区提供的调试工具,同 GCC 配套组成了一套完整的开发环境,GDB 是 Linux 和许多 类Unix系统的标准开发环境。
一般来说,GDB 主要能够提供以下四个方面的帮助:
- 启动程序,可以按照自定义的要求随心所欲的运行程序;
- 可以让被调试的程序在所指定的设置的断点处停住(断点也可以是条件表达式);
- 当程序被停住时,可以检查当前程序的中的变量的状态;
- 可以修改程序,将一个 BUG 产生的影响修正从而测试其他BUG;
2.准备工作
通常,在为调试而编译时,我们需要关掉优化选项 -O ,并且打开调试选项 -g。
另外,-Wall 会在尽量不影响程序行为的情况下选择打开所有的 warning ,也可以发现许多问题,可以避免一些不必要的 BUG。
gcc -g -Wall program.c -o program
-g 选项的作用是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几行,但是并不是把整个源文件嵌入到可执行文件中,所以在调试的时候必须保证 GDB 能找到源文件。
3.GDB命令——启动、退出、查看代码
使用如下的几个文件来测试:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "head.h"
int main(int argc,char* argv[]){
int a , b;
if(argc < 3){
a = 10 , b = 20;
}
else{
a = atoi(argv[1]);
b = atoi(argv[2]);
}
printf("a = %d , b = %d\n",a,b);
printf("a + b = %d\n",add(a,b));
printf("a - b = %d\n",sub(a,b));
printf("a * b = %d\n",mul(a,b));
printf("a / b = %.2lf\n",divide(a,b));
printf("xixixiixixixi\n");
printf("hello makefile\n");
for(int i = 0;i < 20;i++){
printf("%d ",i + 1);
}
printf("\n");
return 0;
}
head.h
#include <stdio.h>
int add(int a,int b);
int sub(int a,int b);
int mul(int a,int b);
double divide(int a,int b);
add.c
#include "head.h"
int add(int a,int b){
return a + b;
}
sub.c
#include "head.h"
int sub(int a,int b){
return a - b;
}
mul.c
#include "head.h"
int mul(int a,int b){
return a * b;
}
div.c
#include "head.h"
double divide(int a,int b){
return a * 1.0 / b;
}
Makefile
src=$(wildcard *.c)
objs=$(patsubst %.c,%.o,$(src))
target=app
$(target):$(src)
$(CC) $(src) -o $(target) -g
.PHONY:clean
clean:
rm $(objs) -f
1.启动和退出
gdb可执行文件;quit / q;
首先使用 make 生成带有调试信息的可执行程序 app,接着再使用 gdb 启动和退出。

2.给程序设置参数 / 获取参数
set args 10 20 ...;show args;

3.GDB 使用帮助
help;

4.查看当前文件代码
list / l(从默认位置开始显示);list / l行号 (从指定行开始显示,指定的行号在中间);list/l函数名 (从指定函数显示);
默认是从起始位置开始显示的。

显示第 20 行。

显示 main 函数。

5.设置显示的行数
show list / listsize;set list / listsize 行数;
默认只显示 10 行。

将其修改为 20 行,再查看代码。

6.查看非当前文件的代码
list / l 文件名:行号;list / l 文件名:函数名;
查看 add.c文件的第 5 行。

查看 sub.c 文件的 sub() 函数。

4.GDB命令——断点操作
1.设置断点
break / b 行号;break / b 函数名;break / b 文件名:行号;break / b 文件名:函数;
默认文件第 10 行设置断点。

main 函数设置断点。

在 add,c 文件中,第 3 行设置断点。

在 sub.c 文件中,sub() 函数设置断点。

2.查看断点
info / i break / b;
查看第一步设置的断点信息。

3.删除断点
delete / del / d 断点编号;
删除编号为 3 的断点,也就是 add.c 第 3 行的断点。

4.设置断点无效
disable / dis 断点编号;
将 1号断点设置为无效。

5.设置断点生效
enable / ena 断点编号;
设置 1号断点 生效。

6.设置条件断点(一般用在循环体中)
break / b 行号 if i==5;
main.c 的 28 行是一个循环,当 i ==10 时,给 28行 设置一个断点。

需要注意的是,当退出 gdb 之后,你之前设置的断点就都没有了。
5.GDB命令——调试命令
1.运行 GDB 程序
start(程序停在第一行);run(遇到断点才停);
给 main.c 的 20行 设置一个断点。
start

run

2.继续运行,遇到下一个断点才停
continue / c;
在 main.c 24行 再设置一个断点。
run 启动程序来到 20行。

接着再执行 continue / c 命令,就会来到下一个断点处,也就是 24行。

如果后面没有断点了,再执行 continue / c 命令,程序就会执行到最后,执行完毕。

3.向下执行一行代码(不会进入函数体)
next / n;
4.变量操作
print 变量名(打印变量的值);ptype 变量名(打印变量数据类型);
5.向下单步调试
step / s(会进入函数体);finish(调出函数体);
6.自动变量操作
display num(自动打印指定变量num的值);info / i display(显示有哪些自动变量);undisplay 编号(取消指定的自动变量);
7.其他操作
set var 变量名=变量值(定义变量);until(跳出循环);



















