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"也被覆盖了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值