Linux內存調試工具YAMD的使用
作者:曾宏安,華清遠見嵌入式學院講師。
C語言作爲應用最爲廣泛的編程語言不僅向程序員提供了功能強大的各種運算符,而且賦予使用者對動態內存分配很大的控制權。在給大家帶來很多便利的同時,這種自由可能會引起嚴重的內存使用問題。這些問題會導致程序崩潰或是隨着時間的推移使得系統性能大幅減低。
內存泄漏和緩衝區溢出是最常見的問題。在複雜的程序中,這類問題很難由程序員直接檢測。在這種情況下,內存調試工具就可以大顯身手,極大的簡化了內存使用問題的檢測工程,提高開發效率。
大家比較熟悉的內存調試工具MEMWATCH就不討論了,這裏向大家介紹另外一個好用的內存調試工具YAMD。(華清遠見原創,轉載請註明出處)
YAMD(Yet Another Malloc Debugger)由Nate Eldredge開發,可檢測C/C++中內存分配相關的問題。常用的版本是0.32,下載源碼包yamd-0.32.tar.gz後解壓並運行make編譯,接着運行make install安裝。
下面演示該工具的使用。程序源代碼test.c如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
int main()
{
char *p1, *p2, *str;
int i;
{
char *p1, *p2, *str;
int i;
p1 = (char *)malloc(100);
p2 = (char *)malloc(100);
str = (char *)malloc(100);
p1 = p2;
for (i=1; i<=100; i++) str[i] = ‘\0’;
free(p1);
free(str);
p2 = (char *)malloc(100);
str = (char *)malloc(100);
p1 = p2;
for (i=1; i<=100; i++) str[i] = ‘\0’;
free(p1);
free(str);
return 0;
}
}
首先編譯test.c生成可執行程序test
# gcc -o test test.c -g –Wall
接着運行yamd和test
# run-yamd ./test 2>test.log
LD_PRELOAD will be “/usr/local/lib/libyamd-dynamic.so”
Running ./test
Temp output to /tmp/yamd-out.18460
*********
*********
Running symify, this may take some time…
Done.
Running ./test
Temp output to /tmp/yamd-out.18460
*********
*********
Running symify, this may take some time…
Done.
查看日誌文件test.log
# cat test.log
# cat test.log
segmentation fault
YAMD version 0.32
Starting run: ./test
Executable: /root/test
Virtual program size is 1868 K
Time is Mon Sep 5 15:26:39 2011
YAMD version 0.32
Starting run: ./test
Executable: /root/test
Virtual program size is 1868 K
Time is Mon Sep 5 15:26:39 2011
default_alignment = 1
min_log_level = 1
repair_corrupted = 0
die_on_corrupted = 1
check_front = 0
min_log_level = 1
repair_corrupted = 0
die_on_corrupted = 1
check_front = 0
INFO: Normal allocation of this block
Address 0xb786df9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048409]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Address 0xb786df9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048409]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
INFO: Normal allocation of this block
Address 0xb786af9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048419]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Address 0xb786af9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048419]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
INFO: Normal allocation of this block
Address 0xb7867f9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048429]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Address 0xb7867f9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048429]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
INFO: Normal deallocation of this block
Address 0xb786af9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048419]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Freed by free at
/lib/libc.so.6(cfree+0xd6)[0x180ec6]
./test[0x8048441]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Address 0xb786af9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048419]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Freed by free at
/lib/libc.so.6(cfree+0xd6)[0x180ec6]
./test[0x8048441]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
ERROR: Crash
./test[0x8048453]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Tried to write address 0xb7868000
Seems to be part of this block:
Address 0xb7867f9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048429]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Address in question is at offset 100 (out of bounds)
Will dump core after checking heap.
./test[0x8048453]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Tried to write address 0xb7868000
Seems to be part of this block:
Address 0xb7867f9c, size 100
Allocated by malloc at
/lib/libc.so.6(__libc_malloc+0x1e0)[0x1810b0]
./test[0x8048429]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./test[0x8048361]
Address in question is at offset 100 (out of bounds)
Will dump core after checking heap.
紅色部分很明確的指出程序在往地址0xb7867f9c的內存寫時出錯,該地址已越界。
靈活的運用各種內存調試工具可以幫助程序員高效的檢測各種內存使用問題,大大提高了開發效率。當然,良好的編程習慣和規範的代碼書寫能有效的避免此類問題的出現。