免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 962 | 回复: 0
打印 上一主题 下一主题

Linux下的调试工具〔转〕 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-20 15:34 |只看该作者 |倒序浏览

                [color="#000102"]      随着[color="#000102"]XP[color="#000102"]的流行,人们越来越注重软件的前期设计、后期的实现,以及贯穿于其中的测试工作,经过这个过程出来的自然是高质量的软件。甚至有人声称[color="#000102"]XP[color="#000102"]会淘汰调试器!这当然是有一定道理的,然而就目前的现实来看,这还是一种理想。在日常工作中,调试工具还是必不可少的。在[color="#000102"]Linux[color="#000102"]下,调试工具并非只有[color="#000102"]gdb[color="#000102"],还有很多其它调试工具,它们都各有所长,侧重方面也有所不同。本文介绍几种笔者常用的调试工具:
[color="#000102"]
[color="#000102"]1.[color="#000102"]         [color="#000102"]mtrace
[color="#000102"]在[color="#000102"]linux[color="#000102"]下开发应用程序,用[color="#000102"]C/C++[color="#000102"]语言的居多。内存泄露和内存越界等内存错误,无疑是其中最头疼的问题之一。[color="#000102"]glibc[color="#000102"]为解决内存错误提供了两种方案:
[color="#000102"]
[color="#000102"]一种是[color="#000102"]hook[color="#000102"]内存管理函数。[color="#000102"]hook[color="#000102"]内存管理函数后,你可以通过记下内存分配的历史记录,在程序终止时查看是否有内存泄露,这样就可以找出内存泄露的地方了。你也可以通过在所分配内存的首尾写入特殊的标志,在释放内存时检查该标志是否被破坏了,这样就可以达到检查内存越界问题的目的。
[color="#000102"]
[color="#000102"]另外一种方法更简单,[color="#000102"]glibc[color="#000102"]已经为第一种方案提供了默认的实现,你要做的只是在特定的位置调用[color="#000102"]mtrace/muntrace[color="#000102"]两个函数,它们的函数原型如下:
[color="#000102"]       [color="#000102"]#include
[color="#000102"]       [color="#000102"]void mtrace(void);
[color="#000102"]void muntrace(void);
[color="#000102"]你可能会问,在哪里调这两种函数最好?这没有固定的答案,要视具体情况而定。对于小程序来说,在进入[color="#000102"]main[color="#000102"]时调用[color="#000102"]mtrace[color="#000102"],在退出[color="#000102"]main[color="#000102"]函数时调用[color="#000102"]muntrace[color="#000102"]。对于大型软件,这样做可能会记录过多的信息,分析这些记录会比较慢,这时可以在你所怀疑代码的两端调用。
[color="#000102"]
[color="#000102"]另外,还需要设置一个环境变量[color="#000102"]MALLOC_TRACE[color="#000102"],它是一个文件名,要保证当前用户有权限创建和写入该文件。[color="#000102"]glibc[color="#000102"]的内存管理器会把内存分配的历史信息写入到[color="#000102"]MALLOC_TRACE[color="#000102"]指定的文件中。
[color="#000102"]
[color="#000102"]程序运行完毕后,使用[color="#000102"]mtrace[color="#000102"]工具分析这些内存分配历史信息,可以查出内存错误的位置([color="#000102"]mtrace[color="#000102"]在[color="#000102"]glibc-utils[color="#000102"]软件包里[color="#000102"])[color="#000102"]。
[color="#000102"]
[color="#000102"]2.[color="#000102"]         [color="#000102"]strace
[color="#000102"]在编程时,检查函数的返回值是一种好习惯。对于像[color="#000102"]glibc[color="#000102"]等标准[color="#000102"]C[color="#000102"]的函数,光检查返回值是不够的,还需要检查[color="#000102"]errno[color="#000102"]的值。这样的程序往往显得冗长,不够简洁。同时也可能是出于偷懒的原因,大多数程序里并没有做这样的检查。
[color="#000102"]
[color="#000102"]这样的程序,一旦出现错误,用调试器一步一步定位错误,然后想法查出错误的原因,也是可以的,不过比较麻烦,对调试器来说有些大材小用,不太可取。这时,用[color="#000102"]strace[color="#000102"]命令可能会更方便一点。它可以显示各个系统调用[color="#000102"]/[color="#000102"]信号的执行过程和结果。比如文件打开出错,一眼就看出来了,连错误的原因[color="#000102"](errno)[color="#000102"]都知道。
[color="#000102"]
[color="#000102"]3.[color="#000102"]         [color="#000102"]binutil
[color="#000102"]binutil[color="#000102"]是一系列的工具,你可能根本不知道它们的存在,但是没有它们你却寸步难行。[color="#000102"]Binutil[color="#000102"]包括下列工具:
[color="#000102"]ld - the GNU linker.[color="#000102"]as - the GNU assembler.[color="#000102"]addr2line[color="#000102"] - Converts addresses into filenames and line numbers.[color="#000102"]ar - A utility for creating, modifying and extracting from archives.[color="#000102"]c++filt - Filter to demangle encoded C++ symbols.[color="#000102"]gprof - Displays profiling information.[color="#000102"]nlmconv - Converts object code into an NLM.[color="#000102"]nm - Lists symbols from object files.[color="#000102"]objcopy - Copys and translates object files.[color="#000102"]objdump - Displays information from object files.[color="#000102"]ranlib - Generates an index to the contents of an archive.[color="#000102"]readelf - Displays information from any ELF format object file.[color="#000102"]size - Lists the section sizes of an object or archive file.[color="#000102"]strings - Lists printable strings from files.[color="#000102"]strip - Discards symbols.[color="#000102"]windres - A compiler for Windows resource files.[color="#000102"]其中部分工具对调试极有帮助,如:
[color="#000102"]你可以用[color="#000102"]objdump[color="#000102"]反汇编,查看目标文件或可执行文件内部信息。
[color="#000102"]你可以用[color="#000102"]addr2line[color="#000102"]把机器地址转换到代码对应的位置。
[color="#000102"]你可以用[color="#000102"]nm[color="#000102"]查看目标文件或可执行文件中的各种符号。
[color="#000102"]       [color="#000102"]你可以用[color="#000102"]gprof[color="#000102"]分析各个函数的使用情况,找出性能的瓶颈所在[color="#000102"]([color="#000102"]这需要加编译选项[color="#000102"])[color="#000102"]。
[color="#000102"]
[color="#000102"]4.[color="#000102"]         [color="#000102"]ld-linux
[color="#000102"]现在加载[color="#000102"]ELF[color="#000102"]可执行文件的工作,已经落到[color="#000102"]ld-linux.so.2[color="#000102"]头上了。你可能会问,这与有调试程序有关系吗?有的。比如,在[color="#000102"]linux[color="#000102"]中,共享库里所有非[color="#000102"]static[color="#000102"]的函数[color="#000102"]/[color="#000102"]全局变量都是[color="#000102"]export[color="#000102"]的,更糟的是[color="#000102"]C[color="#000102"]语言中没有名字空间这个概念,导致函数名极易冲突。在多个共享库中,名字冲突引起的[color="#000102"]BUG[color="#000102"]是比较难查的。这时,你可以通过设置[color="#000102"]LD_ DEBUG[color="#000102"]环境变量,来观察[color="#000102"]ld-linux.so[color="#000102"]加载可执行文件的过程,从中可以得到不少帮助信息。[color="#000102"]LD_ DEBUG[color="#000102"]的取值如下:
[color="#000102"]libs[color="#000102"]        [color="#000102"]display library search paths[color="#000102"]reloc[color="#000102"]       [color="#000102"]display relocation processing[color="#000102"]files[color="#000102"]       [color="#000102"]display progress for input file[color="#000102"]symbols[color="#000102"]     [color="#000102"]display symbol table processing[color="#000102"]bindings[color="#000102"]    [color="#000102"]display information about symbol binding[color="#000102"]versions[color="#000102"]    [color="#000102"]display version dependencies[color="#000102"]all[color="#000102"]         [color="#000102"]all previous options combined[color="#000102"]statistics[color="#000102"] [color="#000102"]display relocation statistics[color="#000102"]unused[color="#000102"]      [color="#000102"]determined unused DSOs[color="#000102"]help[color="#000102"]        [color="#000102"]display this help message and exit[color="#000102"]5.[color="#000102"]         [color="#000102"]gdb
[color="#000102"]对于真正意义的调试器来说,[color="#000102"]gdb[color="#000102"]在[color="#000102"]linux[color="#000102"]下是独一无二的。它有多种包装,有字符界面的,也有图形界面的,有单独运行的,也有集成到[color="#000102"]IDE[color="#000102"]中的。[color="#000102"]gdb[color="#000102"]功能强大,图形界面的[color="#000102"]gdb[color="#000102"]容易上手一点,但功能无疑受到了一些限制,相信大部分高手还是愿意使用字符界面的。[color="#000102"]Gdb[color="#000102"]太常用了,这里不再多说。
[color="#000102"]
[color="#000102"]6.[color="#000102"]         [color="#000102"]gcc/boundschecker
[color="#000102"]相信很多人用过[color="#000102"]win32[color="#000102"]下的[color="#000102"]BoundsChecker(Compuware[color="#000102"]公司[color="#000102"])[color="#000102"]和[color="#000102"]Purify(IBM[color="#000102"]公司[color="#000102"])[color="#000102"]两个工具吧。它们的功能实在太强大了,绝非能通过重载内存管理函数就可以做到,它们在编译时插入了自己的调试代码。
[color="#000102"]
[color="#000102"]gcc[color="#000102"]也有个扩展,通过在编译时插入调试代码,来实现更强大的检查功能。当然这要求重新编译[color="#000102"]gcc[color="#000102"],你可以到
[color="#000102"]http://sourceforge.net/projects/boundschecking/
[color="#000102"] [color="#000102"]下载[color="#000102"]gcc[color="#000102"]的补丁。它的可移植性非常好,笔者曾一个[color="#000102"]ARM [color="#000102"]平台项目里使用过,效果不错。
[color="#000102"]
[color="#000102"]7.[color="#000102"]         [color="#000102"]valgrind
[color="#000102"]最好的东西往往最后才见到。[color="#000102"]Valgrind[color="#000102"]是我的最爱,用习惯了,写的程序不在[color="#000102"]valgrind[color="#000102"]下跑一遍,就像没有写单元测试程序一样,有点放心不下。它有[color="#000102"]BoundsChecker/Purify[color="#000102"]的功能,而且速度更快。
[color="#000102"]
[color="#000102"]有点遗憾的是[color="#000102"]valgrind[color="#000102"]目前只支持[color="#000102"]x86[color="#000102"]平台,当然,这对大多数情况已经足够了。
[color="#000102"]
[color="#000102"]你可以到
[color="#000102"]http://valgrind.org/
[color="#000102"] [color="#000102"]下载最新版本。
               
               
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/104597/showart_2074103.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP