Solaris中如何檢測用戶應用程序內存泄漏

Solaris中如何檢測用戶應用程序內存泄漏

內存泄漏(Memory Leak)通常是由應用程序沒有釋放其在堆(heap)上分配的內存而造成的。
對於由應用程序引起的內存泄漏,我們可以藉助libumem來方便地進行調試。libumem是一個運行在用戶模式的內存分配程序庫。並已包含在 Solaris 9及以後的Solaris版本中。

1 檢測應用程序的內存泄漏

本文將以一個示例簡單說明使用libumem的步驟。示例程序memleak.c如下:
//* memleak.c /*/
1 #include
2 #include
3 int main(void)
4 {
5 char /*p;
6 p = malloc(50);
7 p = malloc(100);
8 while (1) {
9 sleep(1);
10 }
11 }
這個程序存在明顯的內存泄漏。先用gcc編譯該程序
$ /usr/sfw/bin/gcc -o memleak memleak.c
使能libumem,生成core文件。
$ export LD_PRELOAD=libumem.so
$ export UMEM_DEBUG=default
$ export UMEM_LOGGING=transaction
$ ./memleak &
[1] 1121
$ gcore 1121
gcore: core.1121 dumped

用mdb的"::findleaks" 檢測內存泄漏。

$ mdb core.1121
Loading modules: [ libumem.so.1 libc.so.1 ld.so.1 ]
> ::findleaks -> 檢測應用程序中發現的內存泄漏
CACHE LEAKED BUFCTL CALLER
0807c610 1 08088080 main+0x26
------------------------------------------------------------------------
Total 1 buffer, 64 bytes
> 08088080::bufctl_audit -> 打印最後對該內存進行操作的調用棧
ADDR BUFADDR TIMESTAMP THREAD
CACHE LASTLOG CONTENTS
8088080 8086f80 2b73ee921ea 1
807c610 806b000 0
libumem.so.1`umem_cache_alloc_debug+0x14f
libumem.so.1`umem_cache_alloc+0x180
libumem.so.1`umem_alloc+0xcc
libumem.so.1`malloc+0x27
main+0x26
_start+0x80
進一步檢查內存分配日誌如下。就可以看出內存泄漏的原因是應用程序調用了兩次malloc(),但沒有調用free()。
> ::umalog

T-0.000000000 addr=8089f80 umem_alloc_112
libumem.so.1`umem_cache_alloc_debug+0x14f
libumem.so.1`umem_cache_alloc+0x180
libumem.so.1`umem_alloc+0xcc
libumem.so.1`malloc+0x27
main+0x36
_start+0x80

T-0.000052036 addr=8086f80 umem_alloc_64
libumem.so.1`umem_cache_alloc_debug+0x14f
libumem.so.1`umem_cache_alloc+0x180
libumem.so.1`umem_alloc+0xcc
libumem.so.1`malloc+0x27
main+0x26
_start+0x80

2 檢測應用程序內存異常訪問

除了檢測內存泄漏外,libumem還可用於檢測內存異常,如內存越界訪問。簡單修改memleak.c,在第8行

8 p = malloc(50);

後加入如下語句:

memset(p, 60, 0);


重新編譯、運行memleak,並生成core文件。然後用mdb的"::umem_verify"檢測內存越界訪問。

$ mdb core.1168
Loading modules: [ libumem.so.1 libc.so.1 ld.so.1 ]
> ::umem_verify -> 檢測是否存在內存異常
Cache Name Addr Cache Integrity
umem_magazine_1 8077010 clean
umem_magazine_3 8077210 clean
umem_magazine_7 8077410 clean
umem_magazine_15 8077610 clean
umem_magazine_31 8077810 clean
umem_magazine_47 8077a10 clean
umem_magazine_63 8077c10 clean
umem_magazine_95 8077e10 clean
umem_magazine_143 8079010 clean
umem_slab_cache 8079210 clean
umem_bufctl_cache 8079410 clean
umem_bufctl_audit_cache 8079610 clean
umem_alloc_8 8079810 clean
umem_alloc_16 8079a10 clean
umem_alloc_24 8079c10 clean
umem_alloc_32 8079e10 clean
umem_alloc_40 807c010 clean
umem_alloc_48 807c210 clean
umem_alloc_56 807c410 clean
umem_alloc_64 807c610 1 corrupt buffer -> 發現內存異常
umem_alloc_80 807c810 clean
umem_alloc_96 807ca10 clean
> 807c610::umem_verify
Summary for cache 'umem_alloc_64'
buffer 8086f80 (allocated) has a corrupt redzone size encoding
> 8086f80::whatis -> 找到bufctl指針
8086f80 is 8086f80+0, bufctl 8088080 allocated from umem_alloc_64
> 8088080::bufctl_audit -> 打印調用棧以確定異常所在的內存塊
ADDR BUFADDR TIMESTAMP THREAD
CACHE LASTLOG CONTENTS
8088080 8086f80 422098b4141 1
807c610 806b000 0
libumem.so.1`umem_cache_alloc_debug+0x14f
libumem.so.1`umem_cache_alloc+0x180
libumem.so.1`umem_alloc+0xcc
libumem.so.1`malloc+0x27
main+0x26
_start+0x80
> 8086f80/20X -> 打印buffer內容
0x8086f80: 3a 3a10bfc6 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 38df 8088080 a918486d

可以看出內存中有60個字節被設成了0,而該內存實際上只分配了50個有效字節。並且由於內存越界訪問,redzone的標誌字節"feedface"也被覆蓋了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章