一直都用printf进行调试,对于简单的bug还可以,但是,有些bug就有些摸不着头脑。尤其是使用别人的代码,对模块的功能和连接不太熟悉的时候,尤其难调。所以,需要借助一些调试工具来查找执行时错误。

一. gdb

这个工具在做tinyos编程时就遇到过,不过,印象已经不深刻了。

1. 基本使用

   a) $ gdb

   b) (gdb) r executable_file.  

        eg. in ns2, (gdb) ns protocol_test.tcl

   c) (gdb) bt

        Print a backtrace fo the entire stack: one line per frame for all frames in the stack. You can stop the backtrace at any time by typing the system interrupt character, normallyC-c.

        backtrace n (bt n): Similar, but print only the innermost n frames.

   backtrace -n (bt -n): Similar, but print only the outermost n frames.    

        The names where and info stack (abbreviated info s) are additional aliases for backtrace.Each line in the backtrace shows the frame number and the function name. The program counter value is also shown unless you use set print address off. The backtrace also shows the source file name and line number, as well as the arguments to the function. The program counter value is omitted if it is at the beginning of the code for that linenumber.

       Here is an example of a backtrace. It was made with the command `bt 3', so it shows the innermost three frames.

#0  m4_traceon (obs=0x24eb0, argc=1, argv=0x2b8c8)
    at builtin.c:993
#1  0x6e38 in expand_macro (sym=0x2b600) at macro.c:242
#2  0x6840 in expand_token (obs=0x0, t=177664, td=0xf7fffb08)
    at macro.c:71
(More stack frames follow...)

       The display for frame zero does not begin with a program counter value, indicating that your program has stopped at the beginning of the code for line 993 of builtin.c.

二、Valgrind [强烈推荐使用]

1. 使用方法

    a) 基本使用很简单, valgrind executable_file。

       eg. in ns2, valgrind ns protocol_test.tcl

    b)  非常强大。可以指出程序出错的具体函数。

2. 亲身经历

    由于自己以前调bug基本就是靠加printf的。但是,这次很奇怪的是,在tcl中的语句都执行了,但是我认为首先应该执行的函数(ns-source.tcl中的ftp send $nbytes)没有执行。由于我对整个ns2系统的具体调用流程并不是很熟悉,所以,就不知道应该如何调试了,连加printf都不知道在哪里加了。然后就卡了整整4天啊。在时间最宝贵的时候就因为一个segmentation fault卡了四天。周围人都说这是最基本的bug了,应该很容易解决啊。惭愧!!!

   然后,就开始上网查,实际上刚开始遇到bug的时候我就看到有人推荐用gdb和valgrind。但是感觉上使用比较麻烦,就没有认真看如何使用。到后来才发现实际上人家的tool做的很好,初级用法非常傻瓜,对付我这种小程序一个命令足矣了。还是自己太懒惰,不认真看,导致浪费了大好光阴!

   主要输出:Process terminating with default action of signal 11 (SIGSEGV)

==17288==  Access not within mapped region at address 0xBAC9204C

   原因: 有个变量没有初始化,所以,变量值是随机的。这也是为什么有的时候我可以跑70个流的规模,有时候只能跑30个。

   不过,值得高兴的是,有了这次经验,以后调bug应该会更有信心,不要依赖别人!有问题问google.

3. 参考链接

  • http://valgrind.org/

  • http://qinlijiao.blog.sohu.com/113509767.html