调试文件内容gdb.c
#include <stdio.h>
int add_range(int low, int high)
{
int i, sum;
for (i = low; i <= high; i++)
sum = sum + i;
return sum;
}
int main(void)
{
int result[100];
result[0] = add_range(1, 10);
result[1] = add_range(1, 100);
printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);
return 0;
}
编译文件
gcc -g gdb.c -o gdbtest
运行程序
./gdbtest
很明显运行的结果是不对的:1加到10的结果是55,但是1加到100的,结果应该是5050才对,而不是5105,下面用两种gdb方式进行调试
启动gdb
sudo gdb gdbtest
查看文件内容
l
l以后直接进行回车能够查看到后续的内容
断点调试法
设置断点
break 16 #设置16行为断点
break add_range #设置add_range函数为断点
info break #查看断点信息
break在你认为关键的,需要输出的位置进行设置
开启调试
start #运行程序
n #单条语句执行,进入下一条
print i #达因变量i的值
print sum
c #可以想象成continue的功能
当执行完c之后不知道代码执行到那个位置了,可以使用bt进行查看
bt查看函数的堆栈
如下图,表示在gdb.c的文件的第15行的main函数中调用了gdb.c文件中第六航的add_range函数,参数为low=1,high=100
#0 add_range (low=1, high=100) at gdb.c:6
#1 0x0000000100000f07 in main () at gdb.c:15
结论
当我们在调试的时候,可以看出i和sum没有被初始化,而在循环中i进行了初始化,所以问题不大,sum执行完第一次调用后的值是55,所以最终运行完1到10相加,再运行1到100相加的最终结果是5105
顺序调试
查看mian函数,不能发现问题处在哪
首先我们看到gdb停在第14行的位置,执行了add_range的函数调用,正等待我们执行命令
14 result[0] = add_range(1, 10);
接着我们执行了n,gdb执行下一条命令,
15 result[1] = add_range(1, 100);
最后知道输出结果
进入子函数add_range中,查看具体的执行步骤
调试子函数的第一次调用,gdb停留在add_range(1,10)这行代码的位置,直接使用s进入子函数
Temporary breakpoint 3, main () at gdb.c:14
14 result[0] = add_range(1, 10);
(gdb) s
add_range (low=1, high=10) at gdb.c:6
6 for (i = low; i <= high; i++)
接着直接回车进入下一步,在使用info locals进行当前栈帧局部变量的值,也就是add_range函数中i和sum的值
在使用f 1进入1号栈帧也就是main函数中,查看main栈帧局部变量的值(info locals)
本次调用(add_range(1,10))没有错误,直接使用finish运行完当前函数,并让gdb回到main函数中,等待命令发出
让gdb进入下一条命令(n),
(gdb) n
15 result[1] = add_range(1, 100);
再进入子函数(add_range(1,100))中,并查看当前栈帧局部变量的值
(gdb) s
add_range (low=1, high=100) at gdb.c:6
6 for (i = low; i <= high; i++)
发现当前的i和sum没有进行初始化,还是上次函数add_range(1,10)执行完后的结果
(gdb) info locals
i = 11
sum = 55
使用bt查看函数的调用栈(当前调用add_range的蚕食是low=1,high=100),
(gdb) bt
#0 add_range (low=1, high=100) at gdb.c:6
#1 0x0000000100000f07 in main () at gdb.c:15
并进入下一步,设置i和sum的初始值(set var i=0),
(gdb) set var i=0
(gdb) set var sum=0
(gdb) s
7 sum = sum + i;
接着确认当前i和sum的值(p i),
(gdb) p i
$2 = 1
(gdb) p sum
$3 = 0
在用finish连续运行完当前函数,结果返回的值为5050
(gdb) finish
Run till exit from #0 add_range (low=1, high=100) at gdb.c:7
0x0000000100000f07 in main () at gdb.c:15
15 result[1] = add_range(1, 100);
Value returned is $4 = 5050
也就是说,函数返回了正确的结果,错误原因是在第一次add_range的调用之后,没有对i和sum进行初始化
命令总结
命令 描述
backtrace(或bt) 查看各级函数调用及参数
finish 连续运行到当前函数返回为止,然后停下来等待命令
frame(或f) 帧编号 选择栈帧
info(或i)locals 查看当前栈帧局部变量的值
list(或l) 列出源代码,接着上次的位置往下列,每次列10行
list 行号 列出从第几行开始的源代码
list 函数名 列出某个函数的源代码
next(或n) 执行下一行语句
print(或p) 打印表达式的值,通过表达式可以修改变量的值或者调用函数
quit(或q) 退出gdb调试环境
set var 修改变量的值
start 开始执行程序,停在main函数第一行语句前面等待命令
step(或s) 执行下一行语句,如果有函数调用则进入到函数中
next(或n) 执行下一条语句
break 行号 在源码的行数设置断点
break 函数名 在函数的入口处,设置断点
info break 查看断点信息
continue(或c) 继续运行程序
print(或p) 变量名名 打印变量的值
frame(或f) 选择栈帧
set var 修改变量的值
==========
其他事例中没用到的命令
call 函数 调用函数
print 函数 调用函数