C语言debug之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;
}
下面编译并启动debug
gcc -g gdb1.c -lm -o gdb1.out
gdb gdb1.out
如果出现错误的话表示,gdb没有安装。
yum install gdb
安装后再运行以上命令。
下面调试开始,首先start
(gdb) start
Temporary breakpoint 1 at 0x804842c: file gdb1.c, line 16.
Starting program: /var/linux_c/gdb/gdb1.out
Temporary breakpoint 1, main () at gdb1.c:16
warning: Source file is more recent than executable.
16 result[0] = add_range(1,10);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
下面我们要跳入add_range里看一下该函数的执行效果。
(gdb) s
add_range (low=1, high=10) at gdb1.c:6
6 for(i=low;i<=high;i++)
下面打印函数内部的参数,看看他们默认值是多少?
(gdb) i locals
i = 8371516
sum = 8365515
这时我们惊奇的发现sum默认并不是0。这是php跟c的根本区别。c分配的是内存空间。默认这个空间是有值的。还没有完其实默认初始化数组int result[100]时它默认也存在值。下面我们也看一下。首先使用bt查看当前函数的堆栈。
(gdb) bt
#0 add_range (low=1, high=10) at gdb1.c:6
#1 0x08048439 in main () at gdb1.c:16
然后使用f 1返回main的作用域。
(gdb) f 1
#1 0x08048439 in main () at gdb1.c:16
16 result[0] = add_range(1,10);
再使用i locals查看当前变量。
(gdb) i locals
result = {136, 8388548, 0, 8262356, 8262452, 7, 0, 0, 0, 8300418, 8493276, 134513260, -1207961232, -1208025086,
8325437, 134513210, -1207962056, 8388548, 8432592, 2, -1073744676, 8302358, 58190, 8388548, -1073744520, 8276273,
8389916, 8391344, 0, 0, 0, 0, 0, 0, 0, 0, -1207961284, 0, 1114472, 8433112, 8371232, -1073744732, 8468312, 14,
129100401, -1207961284, -163754450, 0, 4, 8390904, 0, 0, 1, 2200, -1207961232, -1207962008, 134513242, 8470392,
134513116, 1, 8388548, -1073744432, 8391344, -1073744476, 8302874, -1073744492, 134513116, -1073744504, 8391252, 0,
-1207961232, 1, 0, 1, 8390904, 1, 164241708, 0, 15774429, 1, 194, 40948, 10060268, 0, -1073744432, 134518504,
-1073744568, 134513392, 11, 134518504, -1073744520, 134513833, 10060268, 134513242, 10071264, 10067956, 134513808,
134513472, 134513819, 10067956}
没错跟预期一样。这时我们发现了问题其实可以直接修改源代码了,其实还可以直接从内存里修改它的值。
(gdb) set var sum=0
(gdb) i locals
i = 8371516
sum = 0
然后直接使用finish完当前函数的return 的结尾。
Run till exit from #0 add_range (low=1, high=10) at gdb1.c:6
0x08048439 in main () at gdb1.c:16
16 result[0] = add_range(1,10);
Value returned is $1 = 55
结果显示为55,表明输出正确。至此代码调试完毕。
附:gdb基础调试命令。
gdb中之断点调试。
主要借助b命令。首先,先把需要调试的代码贴出来。
#include<stdio.h>
int main(void)
{
int sum = 0, i=0;
char input[5];
while(1){
scanf("%s", input);
for(i=0; input[i] != '\0'; i++){
sum = sum*10 + input[i] - '0';
printf("input=%d\n", sum);
}
}
}
跟之前debug程序一样,先敲start
(gdb) start
Temporary breakpoint 1 at 0x804844d: file gdb2.c, line 5.
Starting program: /var/linux_c/gdb/gdb2.out
Temporary breakpoint 1, main () at gdb2.c:5
5 int sum = 0, i=0;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
下面设置两个断点:
(gdb) b 9
Breakpoint 3 at 0x804845d: file gdb2.c, line 9.
(gdb) b 12
Breakpoint 4 at 0x8048484: file gdb2.c, line 12.
下面开始调试这里就不需要跟之前调试一样的。这里只需要c一下程序就行了。它会自动跳转到指定行。
(gdb) c
Continuing.
Breakpoint 2, main () at gdb2.c:9
9 scanf("%s", input);
为便于scanf捕捉输入的内容这里我们需要使用n执行下一行数据。
(gdb) n
123
123为你自己输入的内容。然后再使用c就可以每次循环得出的input数据。如下操作最调试下轮程序时还需要输入个n。
(gdb) c
Continuing.
Breakpoint 3, main () at gdb2.c:12
12 printf("input=%d\n", sum);
(gdb) c
Continuing.
input=1
Breakpoint 3, main () at gdb2.c:12
12 printf("input=%d\n", sum);
(gdb) c
Continuing.
input=12
Breakpoint 3, main () at gdb2.c:12
12 printf("input=%d\n", sum);
(gdb) c
Continuing.
input=123
Breakpoint 2, main () at gdb2.c:9
9 scanf("%s", input);
(gdb) n
23
23为自己输入的内容。下面接着调试主要是n和c两个操作。
(gdb) c
Continuing.
Breakpoint 3, main () at gdb2.c:12
12 printf("input=%d\n", sum);
(gdb) c
Continuing.
input=1232
Breakpoint 3, main () at gdb2.c:12
12 printf("input=%d\n", sum);
上面显示input=1232这里显示就是错的了。因为123是第一次循环的结果。而第二次循环时合并了第一次的结果。表示sum循环时没有初始化。代码修改如下:
#include<stdio.h>
int main(void)
{
int sum = 0, i=0;
char input[5];
while(1){
sum=0;
scanf("%s", input);
for(i=0; input[i] != '\0'; i++){
sum = sum*10 + input[i] - '0';
printf("input=%d\n", sum);
}
}
}