level 11
有了gdb之后大家就可以自己调试程序(这可比vs里的调试要强不少呢)啦
2014年02月02日 05点02分
1
level 11
如果是Linux平台,gdb应该是预装的(额,我的是这样),Windows平台则下载mingw,安装后也就安装好了gdb
2014年02月02日 05点02分
2
gdb可以完全操控程序的运行(不过是dos界面),并且可以查看程序中所有的内部状态(比如各变量的值,传给各函数的参数等等)
2014年02月02日 05点02分
回复 regexepx :额 用错了 sorry
2014年02月02日 08点02分
level 11
看下面的程序:
#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[1000];
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;
}
2014年02月02日 05点02分
3
大家运行下面的代码,结果应该是 result[0]=55 result[1]=5105 第二个结果显然不正确,在小学就知道,高斯算从1加到100应该是5050,但为什么会这样呢,大家先只看代码,待会再来调试
2014年02月02日 05点02分
level 11
在编译时要加上 -g 选项,生成的可执行文件才能用gdb进行源代码级调试:
$ gcc -g main.c -o main
$ gdb main
接下来是一长串的说明信息
然后出现
(gdb)
//gdb提供一个类似shell的命令行环境,上面的(gdb)就是提示符,在这个提示符下输入help可以查看命令的类别:
(gdb) help
List of classes of commands:
.
.
.
也可以进一步查看某一类别中有哪些命令
(gdb)help files
specifying and examining files
.
.
.
现在试试用list命令从第一行列出源代码:
(gdb) list
.
.
.//这里是代码的前十行
现在退出gdb环境:
(gdb)quit
2014年02月03日 13点02分
5
level 11
那么现在开始正式调试程序,按照上面的步骤进入gdb
首先用start命令开始执行程序
(gdb) start
......
14 result[0]=add_range(1,10)
(gdb)
gdb停在main函数中变量定义之后的第一条语句等待我们发命令,我们可以用next命令(简写为n)控制这些语句一条一条执行:
(gdb) n
15 result[1]=add_range(1,100);
(gdb) (直接回车)
16 printf...(这是我省略的,不是gdb)
(gdb) (直接回车)
result[0]=55
result[1]=5105
17 return 0;
虽然我们完全控制了程序的流程,但仍然看不出来哪里错了,现在用start命令来过,这次用step命令(简写s),钻进add_range函数中去跟踪执行:
(gdb) start
...
(gdb) step
add_range (low=1,high=10) at main.c :6
6 for(i=low;i<high;i++)
这次停在了add_range函数变量定义之后的第一条语句处。在函数中有几种查看状态的方法,backtrace命令(简写bt),可以查看函数调用的栈帧:
(gdb) bt
#0 add_range (low=1,high=10) at main.c :6
#1 0x08048429 in main() at main.c :14
可见当前的add_range函数是被main函数调用的,main穿进来的参数是low=1,high=10。main函数的栈帧编号为1,add_range的栈帧编号为0。现在可以用info命令(简写i)查看add_range函数局部变量的值:
(gdb) i locals
i=0
sum=0
到目前为止一切正常,用s或n往下走几步,然后用print(简写为p)打印出sum的值:
(gdb) s
...
(gdb) 回车
...
(gdb) 回车
...
(gdb) 回车
...
(gdb) p sum
$1=3
第一次循环i是1,第二次循环是2,加起来是3,没错,由于我们知道第一次结果正确,在往下跟也就没意义了,可以用finish命令程序一直运行到函数返回:
2014年02月03日 13点02分
6
level 11
(gdb) finish
...
...
14 result[0]=add_range(1,10);
value returned is $2=55
返回值是55
由此可见,第一个值55确实赋给了result的第零个元素,下面用s命令进入第二次add_range函数的调用,进入之后首先查看参数和局部变量:
(gdb) s
...
(gdb) bt
#0 ...
#1 ...
(gdb) i locals
i=11
sum=55
由于局部变量没有初始化,所以具有不确定的值,又由于两次调用是挨在一起的,在for循环中i会赋值为0,但sum如果初值不为零,累加的结果就错了(你会发现,5105正好是55和5050的和),好了,已经找到错误原因,可以退出gdb修改源代码了。
2014年02月03日 13点02分
7
修改就是把add_range函数第一行的int i,sum;改为 int i,sum=0; 这就是一个教训,局部变量在使用前一定要初始化
2014年02月03日 13点02分
回复 regexepx :但是不推荐使用全局变量,如果可以就直接用宏定义常量,避免硬编码
2014年02月04日 02点02分
@IveArthur 对的,C/C++游戏开发也是说最好不用全局变量.不过全局变量可以变啊,常量不能变啊,这一点上不能替换吧
2014年02月04日 02点02分