今天我们利用一个两层函数调用的简单程序——输入两个整数求最大公约数。来学习与理解gdb调试的过程。

首先进行代码编写

main函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>
#include"cal.h"
#include"res.h"
int main()
{
int a,b;
printf("请输入两个数字:\n");
scanf("%d%d", &a, &b);
int res;
res = cal(a,b);
printf("最大公约数是:%d\n",res);
return 0;
}

cal()函数比较两个输入数值大小,并将大的数字放在前面,作为下一个函数的参数:

1
2
3
4
5
6
7
8
9
10
11
#include"res.h"
int cal(int a, int b){
int t;
if(a < b){
t = a;
a = b;
b = t;
}
int r = res(a, b);
return r;
}

res()函数利用辗转相除法求最大公约数:

1
2
3
4
5
6
7
8
9
10
11
12
int res(int a, int b)
{
int m,c;
m = a * b;
c = a % b;
while(c != 0){
a = b;
b = c;
c = a % b;
}
return b;
}

还有两个函数声明的头文件cal.hres.h

cal.h

1
int cal(int a, int b);

res.h

1
int res(int a, int b);

编写Makefile文件,注意需要每一条语句都加上 -g 属性,否则可能会出现有些地方无法调试,比如函数无法单步进入。
在这里插入图片描述
编译链接文件

1
make

在这里插入图片描述
进入main.out程序调试语句

1
gdb main.out

在这里插入图片描述
开始运行函数

1
start

逐条语句执行

1
n

在这里插入图片描述
单步进入函数内

1
s

在这里插入图片描述
查看当前函数调用栈,可以看到这里栈内有两个函数,栈顶是当前进入的cal函数,用于比较两个输入数据的大小并调整顺序。栈底是main函数。

1
bt

在这里插入图片描述
继续执行代码,在执行完判断并交换的逻辑之后,我们可以看到输入时a=33,b=66。现在值已经交换过来了。p命令用于打印某个变量的值。
在这里插入图片描述
在这里插入图片描述

这时可以看到又到了一个函数res这一行,我们再次单步进入,并查看函数栈
在这里插入图片描述

可以看到栈内已经保存了三个函数了。但此时由于参数还没有传进来,所以res的两个参数还是一个系统随机的初始值,我们继续执行一条语句就可以看到参数已经传进来了。
在这里插入图片描述

当我们打印出变量m,c的地址时,由于整形占的是四个字节,可以看到整形变量的地址是连续分配的。
在这里插入图片描述

我们还可以在循环中打印c的值,实时查看辗转相除求最大公约数的过程。
在这里插入图片描述

明白整个过程后,q退出调试。
在这里插入图片描述