(content come from : http://developers.sun.com.cn/blog/judy/entry/200703091)
Solaris中如何检测内存泄漏(一) 在Solaris中如何监测应用程序和核心代码(驱动程序)是否存在内存泄漏?
内存泄漏(Memory Leak)通常是由应用程序没有释放其在堆(heap)上分配的内存而造成的。
对于由应用程序引起的内存泄漏,我们可以借助libumem来方便地进行调试。libumem是一个运行在用户模式的内存分配程序库。并已包含在 Solaris 9及以后的Solaris版本中。
对于内核代码,则可以利用Solaris调试工具mdb提供的"::findleaks"命令来进行检测。
一 利用libumem检测应用程序的内存泄漏
本文将以一个示例简单说明使用libumem的步骤。示例程序memleak.c如下:
/* memleak.c */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p;
p = malloc(50);
p = malloc(100);
while (1) {
sleep(1);
}
}
这个程序存在明显的内存泄漏。先用gcc编译该程序
$ /usr/sfw/bin/gcc -o memleak memleak.c
使能libumem,检测内存泄漏
$ export LD_PRELOAD=libumem.so
$ export UMEM_DEBUG=default
$ export UMEM_LOGGING=transaction
$ ./memleak &
[1] 1121
$ gcore 1121
gcore: core.1121 dumped
$ 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
除了检测内存泄漏外,libumem还可用于检测内存异常,如内存越界访问。简单修改memleak.c,在第8行
p = malloc(50);
后加入如下语句:
memset(p, 60, 0);
重新编译、运行memleak,并生成core文件。
$ 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”也被覆盖了。
(content come from : http://developers.sun.com.cn/blog/judy/entry/200703091)
Solaris中如何检测内存泄漏(一) 在Solaris中如何监测应用程序和核心代码(驱动程序)是否存在内存泄漏?
内存泄漏(Memory Leak)通常是由应用程序没有释放其在堆(heap)上分配的内存而造成的。
对于由应用程序引起的内存泄漏,我们可以借助libumem来方便地进行调试。libumem是一个运行在用户模式的内存分配程序库。并已包含在 Solaris 9及以后的Solaris版本中。
对于内核代码,则可以利用Solaris调试工具mdb提供的"::findleaks"命令来进行检测。
一 利用libumem检测应用程序的内存泄漏
本文将以一个示例简单说明使用libumem的步骤。示例程序memleak.c如下:
/* memleak.c */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p;
p = malloc(50);
p = malloc(100);
while (1) {
sleep(1);
}
}
这个程序存在明显的内存泄漏。先用gcc编译该程序
$ /usr/sfw/bin/gcc -o memleak memleak.c
使能libumem,检测内存泄漏
$ export LD_PRELOAD=libumem.so
$ export UMEM_DEBUG=default
$ export UMEM_LOGGING=transaction
$ ./memleak &
[1] 1121
$ gcore 1121
gcore: core.1121 dumped
$ 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
除了检测内存泄漏外,libumem还可用于检测内存异常,如内存越界访问。简单修改memleak.c,在第8行
p = malloc(50);
后加入如下语句:
memset(p, 60, 0);
重新编译、运行memleak,并生成core文件。
$ 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”也被覆盖了。
(content come from : http://developers.sun.com.cn/blog/judy/entry/200703091)