前期准备
环境设置
首先检查是否安装gdb。如果您的系统中有g++,那么gdb就已经安装了。可以通过在命令行中输入gdb -v来检查是否安装gdb。
Debugging Symbols
gdb只能使用g++产生的symbol进行调试。如果读者使用Sun Cc编译器,那么可以使用一个和gdb很类似到调试工具:dbx
在调试带有debugging symbol的程序时,gdb才能如鱼得水。使用g++的-g选项,即可编译出带有gdb的debugging symbol的程序。除-g选项外,还可以使用-ggdb选项,本文的makefile里面即使用了-ggdb选项。
使用GDB调试
编译程序
首先,切换到含有前面下载的两个文件的目录,然后使用make命令进行编译。
make -f makefile
编译完成后,会生成一个名为main的可执行文件。
加载程序
使用gdb main命令即可将main可执行文件加载到gdb中。在我的终端,使用这个命令的结果如下:
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
Copyright (C) 2010 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-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/jubin/Downloads/gdb_sample/main...done.
(gdb)
(注:在emacs中,您可以使用M-x gdb来在emacs中使用gdb。Emacs将分成两个窗口,第二个窗口将显示代码,并有个箭头指向正在执行的指令所在的代码行。)
gdb启动后,此时正在等待用户输入下一个指令。因为需要查看程序错在哪里,所以首先需要运行这个程序,输入run命令:
(gdb) run
Starting program: /home/jubin/Downloads/gdb_sample/main
Creating Node, 1 are in existence right now
Creating Node, 2 are in existence right now
Creating Node, 3 are in existence right now
Creating Node, 4 are in existence right now
The fully created list is:
4
3
2
1
Now removing elements:
Creating Node, 5 are in existence right now
Destroying Node, 4 are in existence right now
4
3
2
1
Program received signal SIGSEGV, Segmentation fault.
0x08048cb4 in Node<int>::next (this=0x0) at main.cc:30
30Node<T>* next () const { return next_; }
(gdb)
显然,这段程序出错了,下面我们来分析下错误出在什么地方。
检查出错信息
从上面的出错信息可以看出在main.cc的第30行,this指针指向了0。但同时我们还想知道谁调用了第30行,以及调用程序的当时状态。在gdb提示符中输入:backtrace
(gdb) backtrace
#0 0x08048cb4 in Node<int>::next (this=0x0) at main.cc:30
#1 0x08048bea in LinkedList<int>::remove (this=0x804c008, item_to_remove=@0xbffff2c4) at main.cc:79
#2 0x080488d6 in main (argc=1, argv=0xbffff3a4) at main.cc:122
(gdb)
从上面的信息不仅可以看到出错的方法和局部变量,还可以找到调用第30行的程序以及调用时使用的参数item_to_remove的存储地址。x命令可以使我们根据item_to_remove的地址获得item_to_remove的值:
(gdb) x 0xbffff2c4
0xbffff2c4:0x00000001
(gdb)
从上面的信息可以看出,当使用参数“1”调用LinkedList<int>::remove时,程序出错。
条件断点
现在我们知道哪里出错了,下一步要做的是查看在出错前程序的状态。一种方法是步进,直到快出错的那个位置,另一种就是设置断点,在gdb中这样实现:
(gdb) break LinkedList<int>::remove
Breakpoint 1 at 0x8048ab3: file main.cc, line 54.
(gdb)
这样位于 LinkedList<int>::remove的断点“1”就设置好了。如果我们只想查看item_to_remove == 1时的状态,那么需要使用条件断点,在gdb中输入:
(gdb) condition 1 item_to_remove == 1
(gdb)
这个命令的意思是只有在“item_to_remove == 1”的情况下,断点“1”才会生效。
步进
gdb中步进的命令是step。gdb有一个很好的特性,当用户只输入回车时默认执行上一个命令,因此步进时只需在第一步输入step,后面直接敲击回车就可以了。
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/jubin/Downloads/gdb_sample/main
Creating Node, 1 are in existence right now
Creating Node, 2 are in existence right now
Creating Node, 3 are in existence right now
Creating Node, 4 are in existence right now
The fully created list is:
4
3
2
1
Now removing elements:
Creating Node, 5 are in existence right now
Destroying Node, 4 are in existence right now
4
3
2
1
Breakpoint 1, LinkedList<int>::remove (this=0x804c008, item_to_remove=@0xbffff2f4)
at main.cc:54
54 Node<T> *marker = head_;
(gdb) step
55 Node<T> *temp = 0; // temp points to one behind as we iterate
(gdb)
57 while (marker != 0) {
(gdb)
58 if (marker->value() == item_to_remove) {
(gdb)
Node<int>::value (this=0x804c058) at main.cc:32
32 const T& value () const { return value_; }
(gdb)
LinkedList<int>::remove (this=0x804c008, item_to_remove=@0xbffff2f4) at main.cc:77
77 marker = 0; // reset the marker
(gdb)
78 temp = marker;
(gdb)
79 marker = marker->next();
(gdb)
Node<int>::next (this=0x0) at main.cc:30
30 Node<T>* next () const { return next_; }
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0x08048cb4 in Node<int>::next (this=0x0) at main.cc:30
30 Node<T>* next () const { return next_; }
(gdb)
离开gdb的命令:q或quit
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------