在NS2中用GDB来调试

来源:互联网 发布:影子网络 编辑:程序博客网 时间:2024/05/13 09:14

 

原文地址:http://elennatuzi.spaces.live.com/blog/cns!1A9FD94426AD53B!359.entry

 

我想对于用NS来仿真的人来说,很重要的一个问题就是调试,因为并没有像VC那样方便的集成的调试环境。《NS与网络模拟》的书中介绍了tcl debug和KDevelop调试的方法,这里主要介绍gdb调试的方法。因为偶个人第一次写ns代码调试用的就是gdb,感觉安装使用都很方便,这里简单介绍一下:

     1.重新运行cygwin的setup文件,选择gdb组件,下载安装。

     2.修改Makefile,添加调试信息,即CCOPT = -g//(后面可能还有其他参数,保留),其实就是在ns编译的时候gcc后面添加-g选项。

     3.重新编译NS2:make clean,make depend然后make

       我make的时候indep-utils/webtrace-conv/dex/proxytrac2any.cc出了声明错误,在main函数前添加extern int IsLittleEndian(void);extern void ToOtherEndian(TEntry *e);

     常用命令:

     进入gdb调试状态:$gdb ns

     运行脚本:<gdb>r file.tcl

     设置断点:<gdb>b file.cc:行数

     删除断点:<gdb>d b 断点编号(1,2,...)

     显示变量或函数值:<gdb>display var

     删除变量或函数值显示:<gdb>d d 变量编号

     单步执行:<gdb>n

     单步跳入:<gdb>s

     循环执行:<gdb>c

     列出运行栈的内容:<gdb>bt——主要针对遇到segment fault的情况

     退出调试:<gdb>q    

 

 

 

原文地址:http://hi.baidu.com/follow_my_dream_peteryzq/blog/item/0c49fa803fd878a80cf4d29e.html

 

NS2程序的入口点:main函数, (位于ns2.*目录的common子目录的TclAppInit.cc文件)

     main函数中只有两句代码

                  Tcl_Main(argc, argv, Tcl_AppInit);

                   return 0;

   这个函数可以说包装了整个NS2框架,因为紧接着它的下一句语句就是:return 0!

然而,此时,当我们想通过F5(单步跳入)查看TclMain函数的具体实现时,IDE的终端又直接跳至提示符。也就是说,我们仍然无法查看Tcl_Main函数的原型,也就无法查看NS2框架的大部分内容。

我们能查看到 main函数的实现却看不到Tcl_main函数的实现的原因在于: Tcl_Main函数所在的文件并非位于ns2.*目录下,而是位于另一个目录下(后面将看到是tcl8.4.*目录的unix子目录)。而且Tcl_Main函数是被编译到一个静态链接库文件中去了(后面我们将知道是libtcl8.*.a)。 我们此时,只是在ns2.*目录下,用./configure --enable-debug 添加了调试信息,但却没有在 Tcl_Main 函数所在有 tcl8.4.*目录下 添加调试信息(具体来说是在tcl8.4.*unix目录下的Makefile文件中添加 -g选项)

为了能够跟踪到Tcl_Main函数中去,我们作如下操作:

切换到 tcl8.4.*目录的unix子目录,然后 我们会发现 里面有一个libtcl8.*.a 和另一个libtclstub.*.a 文件,前一个大小为700K(这其实是未添加调试信息前的大小)。 再次用make clean命令清除所有目标、库文件后,我们不能再次用sudo ./configure --enable-debug 命令来添加 调试信息(其原因在于此处的 Makefile.in 文件有些特殊)。 我们所要做的是 将 Makefile文件中的 下面内容(102-106)

# To change the compiler switches, for example to change from optimization to
# debugging symbols, change the following line:
#CFLAGS    = $(CFLAGS_DEBUG)
#CFLAGS    = $(CFLAGS_OPTIMIZE)
#CFLAGS    = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)

CFLAGS    = $(CFLAGS_OPTIMIZE) -DTCL_DBGX=$(TCL_DBGX)

换成

# To change the compiler switches, for example to change from optimization to
# debugging symbols, change the following line:
#CFLAGS    = $(CFLAGS_DEBUG)
#CFLAGS    = $(CFLAGS_OPTIMIZE)
CFLAGS    = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)

#CFLAGS    = $(CFLAGS_OPTIMIZE) -DTCL_DBGX=$(TCL_DBGX)

其意思是 将编译械从原来的 优化模式 切换 到 DEBUg+ OPTIMIZE模式。相当于 前面所讲 的 在CCOPT 后添加 -g 选项

然后 ,再次 make ,生成两个新的.a 文件.

注意:在unix目录生成新的.a文件后,须将这两个文件拷贝至 ns-allinone-2.3*lib目录下(因为,在生成NS2时,指定的libtcl8.*.a 的库路径为lib

其实,我们在用make 命令生成NS时,从终端的输出便可以知道NS引用了哪些静态库。为了能够全程调试,这些静态库都应该如libtcl8.*.a库一样,添加调试信息后重新编译生成。

添加调试信息无非就是更改对应的Makefile 中的gcc 编译选项(不同库的Makefile不相同,有的库用 ./configure --enable-debug命令不能添加 调试信息,必须手动修改Makefile)

另外,还需要注意的是:NS所依赖的这些静态库实际上是有相互依赖关系的,因此,重新编译它们,也需要按照一定的顺序。这也是为什么 NSallinone包在安装各个包时,其顺序都是固定的原因。