Chinaunix首页 | 论坛 | 博客
  • 博客访问: 465815
  • 博文数量: 724
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(724)

文章存档

2011年(1)

2008年(723)

我的朋友

分类:

2008-10-13 17:06:13

Debuger功能很强的调试器. 与VC不同, 它的运行库很小, 几乎不用安装. 而且功能与
VC直比相当. gdb与gcc配合使用.

1) 编写调试程序
//main.cpp
#include

#define PRO "helloworld!"

class test
{
public:
    test()
    {
        value = 0;
    }
    test(int newvalue)
    {
        value = newvalue;
    }
   
private:
    int value;
};

int main(int argc, char* argv[])
{
    test obj(12);

    while(--argc != -1)
    {
 printf("%s\n", argv[argc]);
    }   
    printf("%s\n", PRO);

    return 0;
}

2)编译调试代码. gcc使用-g 选项编译调试附加信息.
//Makefile
main.exe : main.o
 g++ main.o -o main.exe

main.o : main.cpp
 g++ -g -c main.cpp -o main.o

3)启动gdb, 加载调试程序.
F:\test>gdb
gdb 5.2.1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-mingw32".
(gdb)
输入file main.exe.
gdb将加载main.exe, 读取执行文件中调试信息.
(gdb) file main.exe
Reading symbols from main.exe...done.
(gdb)
下面我们就要开始正式调试了.


一. 查看源程序.
一个可执行文件可能是由多个源文件来编译生成的.
可以使用list来查看源文件.
list source:linenum
如:
(gdb) list main.cpp:0
1       #include
2
3       class test
4       {
5       public:
6           test()
7           {
8               value = 0;
9           }
10          test(int newvalue)
(gdb)
输入list, 将会继续显示下去
(gdb) list
11          {
12              value = newvalue;
13          }
14
15      private:
16          int value;
17      };
18
19      int main(int argc, char* argv[])
20      {

二.设置断点.
gdb中的断点大致分成三种
breakpoint, watchpoint, catch
其中
breakpoint 是VC中那样的断点, 执行到指定行号或函数时, 程序停下来.
watchpoint 是在指定变量或内存被存取时, 程序停下来.
catch      是在指定事件发生, 如:throw, catch, 动态库加载等时, 程序停下来.
在mingw版本的gdb, 对watchpoint, catch的支持不是很好. mingw没有对watchpoint的硬件
支持, gdb是使用软件摸拟实现watchpoint. 每执行一条语句, 都进判断指定内存是否存取.
这样, 程序运行会变得很慢. 但对于调试这种特殊情况的运行, 速度就变得不是那么重要了
.找bug是第一位的.

1> break location 和 tbreak location
locatcion这么几写法.
LINENUM, 在当前文件上指定行号. 当程序运行到这一行时, 程序停下来.
FUNCTION, 指定函数名. 当程序进入该函数时, 程序停下来. 可以这样写来指定重载函数:
 test(int)
+OFFSET
-OFFSET. 这种写法只有在程序停下来时, 才用得到. 指的当前行上面或下面第OFFSET行设
 置为断点
如果想指定其文件的话. 只需在之前加一个文件名就行了. 如
break stdio.h:printf   ;意思是说在stdio文件中的printf函数设置断点.

tbreak设置的断点是一次性的. t意思就是temp. tbreak在被激发后, 会立即自动删除. 当程序第二
 次回到这个位置时, 就不会停下来了.
下面我想在test的构造函数停下来的话.
(gdb) break test::test(int)
Breakpoint 1 at 0x4018d3: file main.cpp, line 12.
(gdb)

2> wacth EXPR
EXPR是变量或内存地址

3> catch EVENT
`throw'
      有C++异常抛出.

`catch'
      C++异常被catch

`load'
`load LIBNAME'
      动态库被载入

`unload'
`unload LIBNAME'
      动态库被缷载

4> 查看断点和删除断点, 禁用和启用断点
(gdb) info break
Num Type           Disp Enb Address    What
1   breakpoint     keep y   0x004018d3 in test::test(int) at main.cpp:12
(gdb)
可以使用delete NUM来删除断点
(gdb) delete 1
可以使用enable和disable NUM来启用禁用断点
(gdb) disable 1
(gdb) enable 1

5> 给断点添加附加条件.
可以在break, watch命令后面添加if子句, 来指定断点的特点条件
break location if EXPR ;只有当EXPR为true时, 程序才停下来. EXPR是C\C++表达式.
(gdb) break test::test(int) if newvalue==12 ;意思是说只有参数newvalue等于12时,
          程序才在test构造函数上停下来.
Breakpoint 2 at 0x4018d3: file main.cpp, line 12.

也可以使用condition命令来向已经设置好的断点添加条件.
(gdb) condition 2 newvalue==13
(gdb) info break
Num Type           Disp Enb Address    What
2   breakpoint     keep y   0x004018d3 in test::test(int) at main.cpp:12
        stop only if newvalue == 13

6> 给断点添加附加执行命令.
可以使用commands向break, watch断点添加一段gdb命令. 当断点被激发时, 这段gdb命令将
自动被执行.
格式为
commands [BREAKNUM]
cmd-list
end
commands被忽略的话, 将向最后一个断点添加命令.
如:
(gdb) commands 2
Type commands for when breakpoint 2 is hit, one per line.
End with a line saying just "end".
>print "the construct of class test is called.\n"
>end
(gdb)
这样, 当break 2断点被激发时, 将会显示一条信息.

三、运行程序
在设置断点之后, 就要执行命令了.
可以使用set args 来设置程序的执行参数.
(gdb) set args helloworld!
(gdb) show args
Argument list to give program being debugged when it is started is "helloworld!".
(gdb)

使用run命令来执行运行程序, kill强行中止程序运行.
(gdb) file main.exe
(gdb) break test::test(int) if newvalue==12
Breakpoint 1 at 0x4018f3: file main.cpp, line 12.
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>print "the construct of class test is called.\n"
>end
(gdb) run
Starting program: F:\Programmer\mingw/main.exe

Breakpoint 1, test::test(int) (this=0x22ff74, newvalue=12) at main.cpp:12
12              value = newvalue;
$1 = "the construct of class test is called.\n"
(gdb)
看, 我设置的断点被激发了. 并显示了一条信息.
可以使用frame来查看当前执行指针的位置.
(gdb) frame
#0  test::test(int) (this=0x22ff74, newvalue=12) at main.cpp:12
12              value = newvalue;
我们现在位于main.cpp第12行, test(int)构造函数内部. this指针为0x22ff74, 参数
newvalue值为12.

四、调试程序
我们现在可以做这些事情
1> 使用step, next, until, cont来跟踪调用.
step单步跟入.
next单步执行. 遇到函数不进入.
until执行直至函数返回时停下来.
cont断续执行.(Go!)
2> 查看和设置当前环境
可以使用backtrace或bt来查看调用栈
(gdb) bt
#0  test::test(int) (this=0x22ff74, newvalue=12) at main.cpp:12
#1  0x004012cd in main (argc=1, argv=0x3d24d0) at main.cpp:21
(gdb)
我们知道当前我们在test(int)内部, 它是由main.cpp第21行, 主函数中的一条语句执行调
用的.
(gdb) list 21
19      int main(int argc, char* argv[])
20      {
21          test obj(12);
22
23          while(--argc != -1)
如函数被调用多层. 那么bt的返回行信息就会越多.
使用display来查看一些变量或者表达式信息.
(gdb) display this->value
1: this->value = 2
(gdb) display newvalue
2: newvalue = 12
(gdb) display this->value*newvalue
3: this->value * newvalue = 24
(gdb)
可以使用info args来查看函数的参数信息
(gdb) info args
this = (test * const) 0x22ff74
newvalue = 12
同样还有info local查看函数局部变量
info registers查看常用寄存器的值
info all-registers查看所有寄存器的值
info float查看浮点寄存器的值
info vector

不光查看, 我们也可以设置变量的值
(gdb) set this->value=45
(gdb) display this->value
4: this->value = 45
(gdb)

另外可以使用x来查看内存情况.格式是这样的
x/FMT Address
FMT是三部分选项组成的.
F是显示的数量, 比如多少字节.
M是显示的格式, 如:二进制, 十六进制等.
有如下选择
 o(octal) 八进制
 x(hex)  十六进制
 d(decimal) 十进制
 u(unsigned decimal) 无符号十进制
 t(binary) 二进制
 f(float) 浮点表示
 a(address) 地址格式表示
 i(instruction) 汇编指令表示
 c(char)  字符表示
 s(string) 字符串表示
T是单位的大小, 如:是一字节一字节, 还是双字双字的显示
有如下选择
 b(byte)  字节
 h(word=2) 字, 2字节
 w(dword=4) 双字, 4字节
 g(gword=8) 大字, 8字节
例:
(gdb) x/10dw this ;地址为this, 显示10个双字, 格式为十进制
0x22ff74:       45      2293680 4198887 1
0x22ff84:       4007120 4008384 4210688 2293668
0x22ff94:       -1      2293672
(gdb)
那个45就是this->value的值了.

 


--------------------next---------------------

阅读(226) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~