在修正问题之前,您必须找出它的源头。举例来说,对于段错误,您需要了解段错误发生在代码的哪一行。一旦您发现了代码中出错的行,请确定该方法中变量的值、方法被调用的方式以及关于错误如何发生的详细情况。使用调试器将使找出所有这些信息变得很简单。如果没有调试器可用,您还可以使用其它的工具。(请注意,产品环境中可能并不提供调试器,而且 Linux 内核没有内建的调试器。)
实用的内存和内核工具
您可以使用 Linux 上的调试工具,通过各种方式跟踪用户空间和内核问题。请使用下面的工具和技术来构建和调试您的源代码:
用户空间工具:
...
double-free: <4>; test1.c(15), 0x80517b4 was freed from test1.c(14)
...
unfreed: <2>; test1.c(11), 512 bytes at 0x80519e4
{FE FE FE FE FE FE FE FE FE FE FE FE ..............}
Memory usage statistics (global):
N)umber of allocations made: 2
L)argest memory usage : 1024
T)otal of all alloc() calls: 1024
U)nfreed bytes totals : 512
YAMD
YAMD 软件包由 Nate Eldredge 编写,可以查找 C 和 C++ 中动态的、与内存分配有关的问题。在撰写本文时,YAMD 的最新版本为 0.32。请下载 yamd-0.32.tar.gz(请参阅参考资料)。执行 make 命令来构建程序;然后执行 make install 命令安装程序并设置工具。
清单 3. 使用 YAMD 的 test1 输出
YAMD version 0.32
Executable: /usr/src/test/yamd-0.32/test1
...
INFO: Normal allocation of this block
Address 0x40025e00, size 512
...
INFO: Normal allocation of this block
Address 0x40028e00, size 512
...
INFO: Normal deallocation of this block
Address 0x40025e00, size 512
...
ERROR: Multiple freeing At
free of pointer already freed
Address 0x40025e00, size 512
...
WARNING: Memory leak
Address 0x40028e00, size 512
WARNING: Total memory leaks:
1 unfreed allocations totaling 512 bytes
*** Finished at Tue ... 10:07:15 2002
Allocated a grand total of 1024 bytes 2 allocations
Average of 512 bytes per allocation
Max bytes allocated at one time: 1024
24 K alloced internally / 12 K mapped now / 8 K max
Virtual program size is 1416 K
End.
清单 5. 使用 YAMD 的 test2 输出
Running /usr/src/test/test2/test2
Temp output to /tmp/yamd-out.1243
*********
./run-yamd: line 101: 1248 Segmentation fault (core dumped)
YAMD version 0.32
Starting run: /usr/src/test/test2/test2
Executable: /usr/src/test/test2/test2
Virtual program size is 1380 K
...
INFO: Normal allocation of this block
Address 0x40025e00, size 512
...
INFO: Normal allocation of this block
Address 0x40028e00, size 512
...
INFO: Normal allocation of this block
Address 0x4002be00, size 512
ERROR: Crash
...
Tried to write address 0x4002c000
Seems to be part of this block:
Address 0x4002be00, size 512
...
Address in question is at offset 512 (out of bounds)
Will dump core after checking heap.
Done.
Electric Fence
多数 Linux 分发版包含一个 Electric Fence 包,不过您也可以选择下载它。Electric Fence 是一个由 Bruce Perens 编写的 malloc() 调试库。它就在您分配内存后分配受保护的内存。如果存在 fencepost 错误(超过数组末尾运行),程序就会产生保护错误,并立即结束。通过结合 Electric Fence 和 gdb,您可以精确地跟踪到哪一行试图访问受保护内存。Electric Fence 的另一个功能就是能够检测内存泄漏。
清单 9 在向文件系统发出 mount 命令之后显示一个 gdb 异常。kgdb 提供了几条命令,如显示数据结构和变量值以及显示系统中的所有任务处于什么状态、它们驻留在何处、它们在哪些地方使用了 CPU 等等。清单 9 将显示回溯跟踪为该问题提供的信息;where 命令用来执行反跟踪,它将告诉被执行的调用在代码中的什么地方停止。
清单 9. gdb 异常和反跟踪
mount -t jfs /dev/sdb /jfs
Program received signal SIGSEGV, Segmentation fault.
jfs_mount (sb=0xf78a3800) at jfs_mount.c:109
109 printk("%d\n",*ptr);
(gdb)where
#0 jfs_mount (sb=0xf78a3800) at jfs_mount.c:109
#1 0xc01a0dbb in jfs_read_super ... at super.c:280
#2 0xc0149ff5 in get_sb_bdev ... at super.c:620
#3 0xc014a89f in do_kern_mount ... at super.c:849
#4 0xc0160e66 in do_add_mount ... at namespace.c:569
#5 0xc01610f4 in do_mount ... at namespace.c:683
#6 0xc01611ea in sys_mount ... at namespace.c:716
#7 0xc01074a7 in system_call () at af_packet.c:1891
#8 0x0 in ?? ()
(gdb)
3c: 8b 2d 00 00 00 00 mov 0x0,%ebp << problem line above
42: 55 push %ebp
复制代码
kdb
Linux 内核调试器(Linux kernel debugger,kdb)是 Linux 内核的补丁,它提供了一种在系统能运行时对内核内存和数据结构进行检查的办法。请注意,kdb 不需要两台机器,不过它也不允许您像 kgdb 那样进行源代码级别上的调试。您可以添加额外的命令,给出该数据结构的标识或地址,这些命令便可以格式化和显示基本的系统数据结构。目前的命令集允许您控制包括以下操作在内的内核操作:
结束语
帮助调试 Linux 上的程序有许多不同的工具可供使用。本文讲述的工具可以帮助您解决许多编码问题。能显示内存泄漏、溢出等等的位置的工具可以解决内存管理问题,我发现 MEMWATCH 和 YAMD 很有帮助。
使用 Linux 内核补丁会使 gdb 能在 Linux 内核上工作,这对解决我工作中使用的 Linux 的文件系统方面的问题很有帮助。此外,跟踪实用程序能帮助确定在系统调用期间文件系统实用程序什么地方出了故障。下次当您要摆平 Linux 中的错误时,请试试这些工具中的某一个。
参考资料
下载 MEMWATCH。
下载 YAMD。
下载 ElectricFence。
请查看 Dynamic Probes 调试功能程序。
请阅读文章“Linux software debugging with GDB”。(developerWorks,2001 年 2 月)
请访问 IBM Linux Technology Center。
在 developerWorks Linux 专区可以找到更多的 Linux 文章。
关于作者
Steve Best 在位于德克萨斯州奥斯汀的 IBM Linux Technology Center 工作。目前,他在做 Linux 项目的日志纪录文件系统(Journaled File System,JFS)的工作。Steve 在操作系统方面有丰富的从业经验,他的着重的领域是文件系统、国际化和安全性。