目录
1. 创建一个.c文件
建立一个 test.c 文件
代码如下:
#include <stdio.h>
int addToTop(int top)
{
printf("Enter addToTop\n");
int sum = 0;
for(int i = 1; i < top; i++)
{
sum = sum + i;
}
printf("Quit addToTop\n");
return sum;
}
int main()
{
int top = 100;
int result = addToTop(top);
printf("result:%d\n",result);
return 0;
}
2 创建一个Makefile文件
在 .c 文件同一目录下建立一个 Makefile 文件
代码如下:
mytest:test.c
gcc -o mytest test.c
.PHONY:clean
clean:
rm -f mytest
在终端输入 make 会出现如下报错,因为目前此编译器支持的语法不是 C99 标准,所以在Makefile 文件中需要添加新的选项,图示如下:
![]()
添加新的选项,代码如下:mytest:test.c gcc -o mytest test.c -std=c99 .PHONY:clean clean: rm -f mytest
再次执行 make,发现可以进行编译并成功生成了可执行二进制文件,之后就可以对其进行调试,图示如下:
3 调试过程
3.1 创建debug版本的二进制文件
1、在终端输入 gdb test.c 开始进行调试时,会出现报错提示:no debugging symbols found (对应的程序中没有调试信息),图示如下:
因为在 vs 中发布软件有两种方式–debug 版本和 release 版本,debug 版本就是可被调试的版本,而 release 版本是不可被调试的版本(发布版本)。而 linux 下的 gcc/g++ 默认形成的可执行程序是 release 版本的。
解决办法:
在 Makefile 文件的编译选项中添加 -g 选项就让 gcc/g++ 以 debug 的方式编译程序,代码如下:mytest:test.c gcc -o mytest test.c -g -std=c99 .PHONY:clean clean: rm -f mytest
2、将 release 版本的可执行程序命名为 mytest-release,将 debug 版本的可执行程序命名为 mytest-debug 可以看到两个文件大小不一致,debug 版本的大于 release 版本,图示如下:
3.2 调试过程
1、在终端输入 gdb mytest-debug 启动 gdb 调试,图示如下:
2、输入 l 显示代码,输入 l 1 从第一行显示代码,图示如下:
2、继续按 l 或者回车,代码继续向下显示直到全部打印完,图示如下:
3、输入指令 r 执行程序到断点处,如果没断点则直接执行程序结束,图示如下:
4、输入 ”b + 行号“ 设置一个断点,图示如下:
5、输入 “info + b” 查看断点,图示如下:
Enb 表示使能端是否打开,如果打开断点就生效,如果关闭就是断点暂时失效,但是断点还在。如果想暂时使断点失效可以使用命令 “disable breakpoint + 断点编号”,图示如下:
6、输入 “ enable + 断点编号 ” 可以重新打开断点,图示如下:
7、输入 ”r + 回车“ 运行到断点处,图示如下:
8、再次执行 “ info + b” 查看断点信息,可以看到断点被命中了1次,图示如下:
9、使用 “d + 当前断点的编号” 删除断点,图示如下:
10、输入 “quit” 可以退出 gdb 调试,图示如下:
3.3 逐语句和逐过程
1、逐过程:
输入 n 进行逐过程调试。在 gdb 调试中,如果想逐过程调试输入 n 说明直接把函数跑完到达下一行。逐过程指的是以函数为单位不进入函数,直接把函数当成一条语句执行完,然后到函数的下一行,图示如下:
2、逐语句:
逐语句的作用就是找到哪个函数出现问题,然后再进入函数逐语句进行调试。输入 s 进行逐语句调试,逐语句就是进入函数一句一句的进行调试,进入addToTop 函数需要记住两点:调用函数需要将该函数的调用数据进行压栈,并且将调试位置变成整个代码中的第一行,图示如下:
3.4 查看函数调用链
使用命令 bt 查看函数调用链,由于函数调用的过程就是压栈的过程,main 函数在栈底,调用了一个 addToTop 函数,把其放在 main 函数之上,图示如下:
3.5 查看变量的值
使用 ” p + 变量名称 “ 查看变量值,但是想看变量的变化情况需要一直输入 p,不方便,图示如下:
所以需要输入 “ display + 字段名称 ” 进行长显示(可以显示内置类型、结构体等自定义类型、stl),设置好长显示的值后,每次单步执行就更新变量值,如下图所示:
如果不想继续监视某一变量,就输入 “undisplay + 编号 ” 取消字段监视,图示如下:
3.6 until 指令介绍及使用
如果不想打断点,仅仅想把循环跑完就停下,此时输入 “ until 11 ” 将代码直接运行到11行就停下来,图示如下:
3.7 finish指令介绍及使用
gdb 还可以不打断点单独将一个函数运行完,进入需要调试的函数并输入指令 “ finish ”,图示如下:
3.8 从一个断点跳到另一个断点
如果有两个断点,想要从一个断点跳到另一个断点处可以执行命令 c ,直接从一个断点跳到另一个断点处,图示如下: