开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情 @TOC
一、gdb的使用
1. 可执行程序的创建
1. mytest.c
代码语言:javascript复制
vim myetst.c
如果没有创建就会默认创建一个mytest.c文件,并进入vim编辑器
#include<stdio.h>
int mysum(int top)
{
int i=0;
int sum=0;
for(i=1;i<=99;i )
{
sum =i;
}
return sum;
}
int main()
{
printf("proess begin running ...!n");
int result =mysum(100);
printf("result:%dn",result);
printf("proess end running ...!n");
return 0;
}
这里假设函数是计算1到100的和,结果我们只有1到99的和,所以调试寻找哪里错了。
2. makefile
代码语言:javascript复制
vim makefile
如果没有创建就会默认创建一个mytest.c文件,并进入vim编辑器
mytest:mytest.c
gcc $^ -o $@
.PHONY:clean
clean:
rm -f mytest
2. gdb 的安装
代码语言:javascript复制sudo yum install -y gdb
3.使用gdb的过程
1.进入交互模式
输入 gdb ,进入gdb对应的交互模式中
出现红框中的内容说明已经进入交互模式。
2.退出交互模式
输入quit,即可退出交互模式
3. linux默认release版本不可调试
gdb mytest
//上面定义的就为myetst.c文件
输入
gdb mytest
,发现会报错,不是Debug不可以进入调试
1. 将其改成 debug版本
代码语言:javascript复制再次使用
vim makefile
,进入 makefile
mytest_d: mytest.c
gcc $^ -o $@ -g
.PHONY:clean
clean:
rm -f mytest_d
在原本的基础上,加入了
-g
,使程序以debug版本发布
同时为了与之前产生的release版本的mytest 进行区分,使用myetst_d来代替
2.调试
gdb mytest_d
,将不会报错
1. l 行数 ——显示代码
代码语言:javascript复制输入
l 1
,则从第一行开始显示代码
(gdb) l 1
warning: Source file is more recent than executable.
1 #include<stdio.h>
2 int mysum (int top)
3 {
4 int i=0;
5 int sum=0;
6 for(i=1;i<=99;i )
7 {
8 sum =i;
9 }
10 return sum;
代码语言:javascript复制若输入
l 9
,则会将第九行的上下文都打印出来
(gdb) l 9
4 int i=0;
5 int sum=0;
6 for(i=1;i<=99;i )
7 {
8 sum =i;
9 }
10 return sum;
11 }
12 int main()
13 {
显示完整代码
gdb 本身具有记忆命令的能力
在输入l 1
后,再次回车
,就会把将完整代码
显示出来
2. 断点设置 —— b
代码语言:javascript复制
(gdb)b 行号
——断点设置相当于VS中的F9
(gdb) b 14
Breakpoint 1 at 0x4005b8: file mytest.c, line 14.
3. 运行 —— r
代码语言:javascript复制
(gdb)r
——运行,遇到断点就会停止相当于 VS中F5
(gdb) r
Starting program: /home/mydir/test/mytest_d
Breakpoint 1, main () at mytest.c:14
14 printf("proess begin running ...!n");
4. 逐过程——n
代码语言:javascript复制
(gdb) n
——一行一行往下走相当于VS中的F10逐过程
(gdb) n
proess begin running ...!
15 int result =mysum(100);
(gdb) n
16 printf("result:%dn",result);
输入两次 n后,第十五行语句已经执行完,光标指向第十六行,但第十五行处是一个函数,
说明逐过程不进入函数中
5. 查看断点——info b
代码语言:javascript复制
(gdb) info b
——查看断点
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004005b8 in main at mytest.c:14
breakpoint already hit 1 time
记住这里的Num所对应的数字,在后面的删除断点要用
6. 删除断点—— d 编号
代码语言:javascript复制
d 编号
——删除断点
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004005b8 in main at mytest.c:14
breakpoint already hit 1 time
(gdb) d 1
(gdb) info b
No breakpoints or watchpoints.
查看断点时,
Num所对应的数字就是编号
7. 逐语句——s
代码语言:javascript复制
(gdb) s
——逐语句相当于VS中的F11
(gdb) b 15
Breakpoint 4 at 0x4005c2: file mytest.c, line 15.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/mydir/test/mytest_d
proess begin running ...!
Breakpoint 4, main () at mytest.c:15
15 int result =mysum(100);
(gdb) s
mysum (top=100) at mytest.c:4
4 int i=0;
再次使用
b设置断点
在函数第十五行处,再次输入r 运行
,由于处于调试过程中,相当于重新开始
,输入 y回到断点处
发现 输入s
时,可以进入函数中说明逐语句可以进入函数
8. 监视—— display 常量/地址
代码语言:javascript复制
(gdb) display 常量/地址
——地址相当于VS中的监视
6 for(i=1;i<=99;i )
(gdb) display sum
1: sum = 0
(gdb) display i
2: i = 0
(gdb) s
8 sum =i;
2: i = 1
1: sum = 0
(gdb) s
6 for(i=1;i<=99;i )
2: i = 1
1: sum = 1
代码语言:javascript复制通过不断
s
,使光标处于for循环处,随着光标向下移,sum和i也随之改变
(gdb) display &i
3: &i = (int *) 0x7fffffffe46c
(gdb) s
8 sum =i;
3: &i = (int *) 0x7fffffffe46c
2: i = 2
1: sum = 1
(gdb) s
6 for(i=1;i<=99;i )
3: &i = (int *) 0x7fffffffe46c
2: i = 2
1: sum = 3
也可以直接监视地址的变化
9.去除监视——undisplay 编号
代码语言:javascript复制
(gdb) undisplay 编号
——去除监视
(gdb) s
6 for(i=1;i<=99;i )
3: &i = (int *) 0x7fffffffe46c
2: i = 2
1: sum = 3
(gdb) undisplay 3
(gdb) s
8 sum =i;
2: i = 3
1: sum = 3
(gdb) display 2
4: 2 = 2
(gdb) s
6 for(i=1;i<=99;i )
4: 2 = 2
2: i = 3
1: sum = 6
在每次显示sum和i与i
冒号的前面的1 2 3
就为编号
10 跳转至指定行——until 行数
代码语言:javascript复制
until 行数
——跳转至指定行
(gdb) s
5 int sum=0;
(gdb) s
6 for(i=1;i<=99;i )
(gdb) until 10
mysum (top=100) at mytest.c:10
10 return sum;
光标刚开始在第6行的for循环处,until后直接跳出循环
11 .运行至下一个断点处——c
(gdb) c
——运行至下一个断点处相当于VS中再次使用F5
有两个断点分别在 6行和8行
运行后处于第6行的断点处,使用c后,处于第8行的断点处