linux下的调试工具-凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 139023
  • 博文数量: 41
  • 博客积分: 51
  • 博客等级: 民兵
  • 技术积分: 225
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-31 22:53
文章分类
文章存档

2013年(15)

2012年(25)

2011年(1)

分类:

2013-01-08 14:41:11

原文地址: 作者:


转载时请注明出处和作者凯发app官方网站的联系方式
文章出处:
作者凯发app官方网站的联系方式:李先静

随 着xp的流行,人们越来越注重软件的前期设计、后期的实现,以及贯穿于其中的测试工作,经过这个过程出来的自然是高质量的软件。甚至有人声称xp会淘汰调 试器!这当然是有一定道理的,然而就目前的现实来看,这还是一种理想。在日常工作中,调试工具还是必不可少的。在linux下,调试工具并非只有gdb, 还有很多其它调试工具,它们都各有所长,侧重方面也有所不同。本文介绍几种笔者常用的调试工具:

1. mtrace

在linux下开发应用程序,用c/c 语言的居多。内存泄露和内存越界等内存错误,无疑是其中最头疼的问题之一。glibc为解决内存错误提供了两种方案:

一种是hook内存管理函数。hook内存管理函数后,你可以通过记下内存分配的历史记录,在程序终止时查看是否有内存泄露,这样就可以找出内存泄 露的地方了。你也可以通过在所分配内存的首尾写入特殊的标志,在释放内存时检查该标志是否被破坏了,这样就可以达到检查内存越界问题的目的。

另外一种方法更简单,glibc已经为第一种方案提供了默认的实现,你要做的只是在特定的位置调用mtrace/muntrace两个函数,它们的函数原型如下:

#include

void mtrace(void);

void muntrace(void);

你可能会问,在哪里调这两种函数最好?这没有固定的答案,要视具体情况而定。对于小程序来说,在进入main时调用mtrace,在退出main函 数时调用muntrace。对于大型软件,这样做可能会记录过多的信息,分析这些记录会比较慢,这时可以在你所怀疑代码的两端调用。

另外,还需要设置一个环境变量malloc_trace,它是一个文件名,要保证当前用户有权限创建和写入该文件。glibc的内存管理器会把内存分配的历史信息写入到malloc_trace指定的文件中。

程序运行完毕后,使用mtrace工具分析这些内存分配历史信息,可以查出内存错误的位置(mtrace在glibc-utils软件包里)。

2. strace

在编程时,检查函数的返回值是一种好习惯。对于像glibc等标准c的函数,光检查返回值是不够的,还需要检查errno的值。这样的程序往往显得冗长,不够简洁。同时也可能是出于偷懒的原因,大多数程序里并没有做这样的检查。

这样的程序,一旦出现错误,用调试器一步一步定位错误,然后想法查出错误的原因,也是可以的,不过比较麻烦,对调试器来说有些大材小用,不太可取。 这时,用strace命令可能会更方便一点。它可以显示各个系统调用/信号的执行过程和结果。比如文件打开出错,一眼就看出来了,连错误的原因 (errno)都知道。

3. binutil

binutil是一系列的工具,你可能根本不知道它们的存在,但是没有它们你却寸步难行。binutil包括下列工具:

* ld - the gnu linker.
* as - the gnu assembler.
* addr2line - converts addresses into filenames and line numbers.
* ar - a utility for creating, modifying and extracting from archives.
* c filt - filter to demangle encoded c symbols.
* gprof - displays profiling information.
* nlmconv - converts object code into an nlm.
* nm - lists symbols from object files.
* objcopy - copys and translates object files.
* objdump - displays information from object files.
* ranlib - generates an index to the contents of an archive.
* readelf - displays information from any elf format object file.
* size - lists the section sizes of an object or archive file.
* strings - lists printable strings from files.
* strip - discards symbols.
* windres - a compiler for windows resource files.

其中部分工具对调试极有帮助,如:

你可以用objdump反汇编,查看目标文件或可执行文件内部信息。

你可以用addr2line把机器地址转换到代码对应的位置。

你可以用nm查看目标文件或可执行文件中的各种符号。

你可以用gprof分析各个函数的使用情况,找出性能的瓶颈所在(这需要加编译选项)。

4. ld-linux

现在加载elf可执行文件的工作,已经落到ld-linux.so.2头上了。你可能会问,这与有调试程序有关系吗?有的。比如,在linux中, 共享库里所有非static的函数/全局变量都是export的,更糟的是c语言中没有名字空间这个概念,导致函数名极易冲突。在多个共享库中,名字冲突 引起的bug是比较难查的。这时,你可以通过设置ld_ debug环境变量,来观察ld-linux.so加载可执行文件的过程,从中可以得到不少帮助信息。ld_ debug的取值如下:

* libs display library search paths
* reloc display relocation processing
* files display progress for input file
* symbols display symbol table processing
* bindings display information about symbol binding
* versions display version dependencies
* all all previous options combined
* statistics display relocation statistics
* unused determined unused dsos
* help display this help message and exit

5. gdb

对于真正意义的调试器来说,gdb在linux下是独一无二的。它有多种包装,有字符界面的,也有图形界面的,有单独运行的,也有集成到ide中 的。gdb功能强大,图形界面的gdb容易上手一点,但功能无疑受到了一些限制,相信大部分高手还是愿意使用字符界面的。gdb太常用了,这里不再多说。

6. gcc/boundschecker

相信很多人用过win32下的boundschecker(compuware公司)和purify(ibm公司)两个工具吧。它们的功能实在太强大了,绝非能通过重载内存管理函数就可以做到,它们在编译时插入了自己的调试代码。

gcc也有个扩展,通过在编译时插入调试代码,来实现更强大的检查功能。当然这要求重新编译gcc,你可以到 下载gcc的补丁。它的可移植性非常好,笔者曾一个arm 平台项目里使用过,效果不错。

7. valgrind

最好的东西往往最后才见到。valgrind是我的最爱,用习惯了,写的程序不在valgrind下跑一遍,就像没有写单元测试程序一样,有点放心不下。它有boundschecker/purify的功能,而且速度更快。

有点遗憾的是valgrind目前只支持x86平台,当然,这对大多数情况已经足够了。

你可以到 下载最新版本。

阅读(1216) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图