gdb第一次调试使用 my.oschina.net/jl88747653/blog/87732

来源:互联网 发布:淘宝卖家在哪找货源 编辑:程序博客网 时间:2024/06/11 08:42

这篇文章是初次尝试GDB调试后写的,这个案例结合了我个人的分析,在GDB第一次运行当中遇到困难的可以看一看。

开始接触linux内核的第二天,学的是一段小小的编程,然后实验就是使用GDB调试并纠错,这里附上代码:

/*  这是一个有错误的C程序   */
#include <stdio.h>
#include <stdlib.h>

static char buff[256];
static char* string;
int main()
{
    printf("Please input your string:");
    gets(string);
    printf("\nYour string is:%s\n",string);
}

目的很明显,就是手动输入一段字符串,再由计算机获得数据并实现输出,也就是说,输入什么,就要输出什么。

用Gedit写好程序,保存为test.c,然后开始使用gcc编译。
在终端输入gcc + xx.c 即可调用gcc进行编译: gcc -g test.c -o test(注意:这里我把经过编译后的test.c输出为test,否则默认输出是a.out,这里-o就是指定文件名的作用了。-g选项在可执行文件中加上源文件信息.)

我们可以看到,编译完成之后,文件夹下多出了一个可执行文件,即编译完成后的test。
在终端下输入:./test  即可运行该程序。试运行:
$ ./test
Please input your string:as                        -------提示输入字符串
Segmentation fault(core dumped)         -------段错误(吐核)

解释一下段错误及其原因和解决方案请看这里: http://my.oschina.net/jl88747653/blog/87685

接下来开始GDB调试。
GDB 是一个用来调试 C 和 C++ 程序的强力调试器,它使你能在程序运行时观察程序的内部结构和内存的使用情况。 以下是 gdb 所提供的一些功能:
  • 监视程序中变量的值.
  • 设置断点以使程序在指定的代码行上停止执行
  • 一行行的执行代码(或者说,具备逐行纠错的能力吧)
终端输入:$ gdb test
GNU gdb (GDB) Fedora (7.4.50.20120120-52.fc17)
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...【以上是GNU GDB的一些信息,相当于简单的版本说明书,你可以当成是一堆废话】
Reading symbols from /home/xin/文档/huibian/bugging/test...done.【加载或读取test】

(gdb) 【看到(gdb)就代表着进入了GDB的编辑区域了!!!】
加载之后,首先得启动吧,执行:
(gdb) run
Starting program: /home/xin/文档/huibian/bugging/test
Please input your string:as【跟gcc编译时一样,提示输入字符串】

Program received signal SIGSEGV, Segmentation fault.【同样出现了段错误】
_IO_gets (buf=0x0) at iogets.c:55
55          buf[0] = (char) ch;
【上面两行马上会在下面提到,看楼下~~】
执行查找错误使用where命令:
(gdb) where
#0  _IO_gets (buf=0x0) at iogets.c:55
#1  0x08048452 in main () at test.c:9


为了这两句话和之前的“段错误”,花了奖近两个小时的时间投入,理解了很久,才终于想通了是什么意思,百度google上大都是讲解决方法,至于是什么意思,几乎没有提到,不然就是很模糊不清,根据我的理解是这样的:
#0  _IO_gets (buf=0x0) at iogets.c:55 ———gets函数的缓冲区溢出错误;
#1 0x08048452 in main () at test.c:9  ———由于上面的缓冲区溢出错误,使得在test.c文件中的第9行调用main函数也出现了错误(注:0x08048452是缓冲区溢出的一种表现
 

由上面的分析知道,在第9行出现的错误,即gets(string)附近,使用list命令查看即9行附近的代码:
(gdb) list test.c:9
1    #include <stdio.h>
2    #include <stdlib.h>
3   
4    static char buff[256];
5    static char* string;
6    int main()
7    {
8        printf("Please input your string:");
9       gets(string);

查看命令,是没有问题的,唯一值得怀疑的是变量string,我们用print命令查看string的值:
(gdb) print string
$1 = 0x0【可以看到,string的值为0,这时
gets 函数传递了一个空指针,这就是程序的错误所在。这是因为 string 是 
一个全局变量,运行时初始化为 0,即空指针,并没有指向一个函数


确定错误的地方,然后就是修正了。gdb提供了断点修正的方法,也就是在出错的地方加上一个断点,程序运行到这个地方就会暂停,然后从这个断点开始错误排查,不断进行修正。于是我们第一步要走的就是加断点:
(gdb) break 9
 Breakpoint 1 at 0x8048452: file test.c, line 9.
再次启动:
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/xin/文档/huibian/bugging/test
Please input your string:as

Program received signal SIGSEGV, Segmentation fault.
_IO_gets (buf=0x0) at iogets.c:55
55          buf[0] = (char) ch;


 就可以使用set variable命令可以修改string的值了:
(gdb) set variable string=buff
(gdb) continue
Continuing.
Please input a string: as

Your string is: as【正确输出】

Program exited with code 023.

说明修改是正确的。
但是这还没结束,gdb的作用只是调试,并非真正的修改,我们可以理解为是在虚拟机里的试运行,它修改的数据并不会实时地反馈并保存在源数据当中,所以要想下次不再出错,必须回到源文件进行对应的修改,于是源代码变为:
#include <stdio.h>
#include <stdlib.h>

static char buff[256];
static char* string;
int main()
{
    printf("Please input your string:");
    string=buff;
    gets(string);
    printf("\nYour string is:%s\n",string);
}
重新编译,运行:
 
$ ./test
Please input your string:as

Your string is:as
 

这次成功完成了!!! (撒花!!!~~
0 0
原创粉丝点击