Linux下的用户空间调试工具和技术,它们用来分析用户空间的问题相当有用,主要有下面几种:
- 1.printf打印
- 2./proc查询
- 3.strace和ltrace
- 4.Valgrind
- 5.gdb
- 6.splint静态分析工具
- 7.prof/gprof性能分析工具
- 8.ElectricFence内存调试
- 9.binutil系列工具
<h3 id="1">1.printf打印</h3>
这是一个基本的原始的调试问题的方法。 我们可以在程序中插入print语句来了解控制流和变量值。 虽然这是一个简单的技术, 但它有一些缺点。 程序需要进行编辑以添加'print'语句,然后必须重新编译,重新运行来获得输出。 如果要调试的程序相当大,这是一个耗时的方法。
<h3 id="2">2./proc查询</h3>
在某些情况下,我们需要弄清楚在一个运行在内核中的进程的状态和内存映射。为了获得这些信息,我们可以用 /proc 文件系统。
/proc 是一个伪文件系统,系统一启动运行就收集着运行时系统的信息 (cpu信息, 内存容量等)。
一些有用的列举如下:
/proc/cmdline -> 内核命令行
/proc/cpuinfo -> 关于处理器的品牌,型号信息等
/proc/filesystems -> 文件系统的内核支持的信息
/proc/<pid>/cmdline -> 命令行参数传递到当前进程
/proc/<pid>/mem -> 当前进程持有的内存
/proc/<pid>/status -> 当前进程的状态
<h3 id="3">3.strace和ltrace</h3>
strace拦截和记录系统调用及其接收的信号。对于用户,它显示了系统调用、传递给它们的参数和返回值。strace的可以附着到已在运行的进程或一个新的进程。它作为一个针对开发者和系统管理员的诊断、调试工具是很有用的。它也可以用来当做一个通过跟踪不同的程序调用来了解系统的工具。这个工具的好处是不需要源代码,程序也不需要重新编译。
ltrace跟踪和记录一个进程的动态(运行时)库的调用及其收到的信号。它也可以跟踪一个进程所作的系统调用。它的用法是类似与strace。
<h3 id="4">4.Valgrind</h3>
Valgrind手册
http://valgrind.org/docs/manual/mc-manual.html#mc-manual.leaks
Valgrind是一套调试和分析工具。它的一个被广泛使用的默认工具——'Memcheck'——可以拦截malloc(),new(),free()和delete()调用。换句话说,它在检测下面这些问题非常有用:
内存泄露
重释放
访问越界
使用未初始化的内存
使用已经被释放的内存等。
Valgrind包括以下工具:
4.1 Memcheck
Memcheck 工具主要检查下面的程序错误:
使用未初始化的内存(Use of uninitialised memory)
使用已经释放了的内存(Reading/writing memory after it has been free'd)
使用超过malloc分配的内存空间(Reading/writing off the end of malloc'd blocks)
对堆栈的非法访问(Reading/writing inappropriate areas on the stack)
申请的空间是否有释放(Memory leaks – where pointers to malloc'd blocks are lost forever)
malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)
一般常用命令
valgrind --leak-check=full --tool=memcheck runprogram
4.2 Callgrind
Callgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式
4.3 Cachegrind
它模拟CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助
4.4 Helgrind
它主要用来检查多线程程序中出现的竞争问题。Helgrind 寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为" Eraser" 的竞争检测算法,并做了进一步改进,减少了报告错误的次数
4.5 Massif
堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率
<h3 id="5">5.gdb</h3>
常用命令:
run
set args
bt: 打印整个堆栈的回溯
bt 打印n个帧的回溯
frame : 切换到指定的帧,并打印该帧
up : 上移'n'个帧
down : 下移'n'个帧 ( n默认是1)
print
list : 列出'linenum'行周围的源码
list : 从'function'开始列出源码
disas : 显示该函数机器代码
break : 在'location'设置一个断点。当在程序执行到这里时断点将被击中,控制权被交给用户。
watch : 当'expr'被程序写入而且它的值发生变化时GDB将停止
catch : 当'event'发生时GDB停止
disable : 禁用指定断点
enable : 启用指定断点
delete : 删除 断点/观察点/捕获点。 如果没有传递参数默认操作是在所有的断点
step: 一步一步执行程序
continue: 继续执行程序,直到执行完毕
quit
<h3 id="6">6.splint静态分析工具</h3>
splint手册
http://www.splint.org/manual/manual.html#memory
<h3 id="7">7.prof/gprof性能分析工具</h3>
gprof手册
http://sourceware.org/binutils/docs-2.17/gprof/index.html
<h3 id="8">8.ElectricFence内存调试</h3>
efence手册
(1)man efence
(2)http://linux.die.net/man/3/efence
<h3 id="9">9.binutil系列工具</h3>
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分析各个函数的使用情况,找出性能的瓶颈所在(这需要加编译选项)。