linux pmap 内存泄露,pmap学习:系统测试中怎么确定内存泄露(memory leak)

标签:

pmap is a good tool to report the memory map of a process. But how to make sure a process has memory leak, here is the tips:

1, if the virtual memory (VIRT) or writeable/private (‘pmap –d’ output) keeps increasing stably when you repeat the same operation, it should be have memory leak.

2, The RSS is just for your reference, it can’t used as the factor to detect memory leak.

3, although you call ‘free’ or ‘delete’, the virtual memory may not shrink immediately.

4, the same new operation may mapped to different [anon] virtual memory space. Here 1M was alloated to000000001b56a000and00002ac25a77c000.

000000001b56a00011561212 rw---[ anon ]

00002ac25a77c00010401616 rw---[ anon ]

Test Code:

#include "stdio.h"

int global_i_init=0;

static int static_global_j=11;

int global_k;

int main () {

int tmp;

printf ("global_i_init: 0x%lx\n",&global_i_init );

printf ("global_k non_init : 0x%lx\n",&global_k );

printf ("static_global_j  : 0x%lx\n",&static_global_j );

printf ("stack i  : 0x%lx\n",&tmp );

getchar (); // step2

char *x= new char[100*1024];

printf ("data allocate 100k @0x%lx\n", x);

getchar();  // step3

char *x2= new char[1024*1024];

printf ("data allocate 1M i@0x%lx\n", x2);

getchar(); // step4

printf ("data write at x2[1024*1024-1] ");

x2[1024*1024-1]=0;

getchar(); // step5

printf ("data read at x2 ");

int j;

for (int i=0;i<1024*1024; i++)

j=x2[i];

getchar (); // step6

printf ("delete x2");

delete x2;

getchar ();  //step 7

printf ("delete x");

delete x;

getchar();  //step8

x2= new char[1024*1024];

printf ("data allocate 1M i@0x%lx\n", x2);

getchar ();

}

Program output:

ATCA48-0-0-1:/root-# ./a.out

global_i_init: 0x500cc0

global_k non_init : 0x500cc4

static_global_j  : 0x500cb8

stack i  : 0x7fff0120ab5c

data allocate 100k @0x1b56a010

data allocate 1M i@0x2ac25a77f010

data write at x2[1024*1024-1]

data read at x2

delete x2

delete x

data allocate 1M i@0x1b56a010

最后一行的值

mapped 表示该进程映射的虚拟地址空间大小,也就是该进程预先分配的虚拟内存大小,即ps出的vsz

writeable/private  表示进程所占用的私有地址空间大小,也就是该进程实际使用的内存大小

shared 表示进程和其他进程共享的内存大小

pmap -d output:

mapped

writeable/private:

shared

STEP 1

init

19616K

236K

0

STEP 2

new 100k

19848K

468K

0

STEP 3

new 1M

20876K

1496K

0

STEP 4

write 1 byte

20876K

1496K

0

STEP 5

read 1M

20876K

1496K

0

STEP 6

delete 1M

19848K

468K(没有变化)

0

STEP 7

delete 100k

19848K

468K(没有变化)

0

STEP 8

new 1M

20772K

1392K

0

pmap -d conclusion:

1, mapped and writeable/private can reflect the memory variation.

mapped 和writeable/private 能够反映内存的变化.

2, delete or free may not decrease mapped or writeable/private immediately.

delete 和free 不能在 mapped 和writeable/private 立即反映出来,比方删除100k就没有变化

pmap -x output:

Total kbytes

RSS

Dirty

STEP 1

init

19616

912

124

STEP 2

new 100k

19848

976

140

STEP 3

new 1M

20876

980

144

STEP 4

write 1 byte

20876

984

148

STEP 5

read 1M

20876

2004

148

STEP 6

delete 1M

19848

976

140

STEP 7

delete 100k

19848

980

140

STEP 8

new 1M

20772

984

144

Address

kbytes

RSS

Dirty

STEP 1

init

STEP 2

new 100k

000000001b56a000

232

8

8

STEP 3

new 1M

000000001b56a000

232

8

8

STEP 4

write 1 byte

000000001b56a000

232

8

8

STEP 5

read 1M

000000001b56a000

232

8

8

STEP 6

delete 1M

000000001b56a000

232

8

8

STEP 7

delete 100k

000000001b56a000

232

8

8

STEP 8

new 1M

000000001b56a000

1156

12

12

Address

kbytes

RSS

Dirty

STEP 1

init

00002ac25a77c000

12

12

12

STEP 2

new 100k

00002ac25a77c000

12

12

12

STEP 3

new 1M

00002ac25a77c000

1040

16

16

STEP 4

write 1 byte

00002ac25a77c000

1040

20

20

STEP 5

read 1M

00002ac25a77c000

1040

1040

20

STEP 6

delete 1M

00002ac25a77c000

12

12

12

STEP 7

delete 100k

00002ac25a77c000

12

12

12

STEP 8

new 1M

00002ac25a77c000

12

12

12

pmap -x conclusion:

pmap -x 结论

1, although you used new(step 3), the OS didn‘t commit the memory page until you read (STEP5)or write(STEP4) that memory space.

尽管你已经调用了 new分配内存(step 3), 但是 OS不一定一下把所有的page都分配。本例中只有对那一块已经分配内存进行读 (STEP5)或者写(STEP4) 的时候才提交实际内存

pmap -x:

2, the new memory operation maybe happened on different Address range. like the first 1M allcation at00002ac25a77c000, but the 2nd 1M allcation happened at 000000001b56a000

Final pmap -d:

Address           Kbytes Mode  Offset           Device    Mapping

0000000000400000       4 r-x-- 0000000000000000 008:00001 a.out

0000000000500000       4 rw--- 0000000000000000 008:00001 a.out

000000001b56a000    1156 rw--- 000000001b56a000 000:00000   [ anon ]

0000003677000000     112 r-x-- 0000000000000000 008:00001 ld-2.5.so

000000367721c000       4 r---- 000000000001c000 008:00001 ld-2.5.so

000000367721d000       4 rw--- 000000000001d000 008:00001 ld-2.5.so

0000003677400000    1336 r-x-- 0000000000000000 008:00001 libc-2.5.so

000000367754e000    2048 ----- 000000000014e000 008:00001 libc-2.5.so

000000367774e000      16 r---- 000000000014e000 008:00001 libc-2.5.so

0000003677752000       4 rw--- 0000000000152000 008:00001 libc-2.5.so

0000003677753000      20 rw--- 0000003677753000 000:00000   [ anon ]

0000003677c00000     520 r-x-- 0000000000000000 008:00001 libm-2.5.so

0000003677c82000    2044 ----- 0000000000082000 008:00001 libm-2.5.so

0000003677e81000       4 r---- 0000000000081000 008:00001 libm-2.5.so

0000003677e82000       4 rw--- 0000000000082000 008:00001 libm-2.5.so

0000003678c00000      52 r-x-- 0000000000000000 008:00001 libgcc_s-4.1.2-20080825.so.1

0000003678c0d000    2048 ----- 000000000000d000 008:00001 libgcc_s-4.1.2-20080825.so.1

0000003678e0d000       4 rw--- 000000000000d000 008:00001 libgcc_s-4.1.2-20080825.so.1

0000003679400000     920 r-x-- 0000000000000000 008:00001 libstdc++.so.6.0.8

00000036794e6000    2044 ----- 00000000000e6000 008:00001 libstdc++.so.6.0.8

00000036796e5000      24 r---- 00000000000e5000 008:00001 libstdc++.so.6.0.8

00000036796eb000      12 rw--- 00000000000eb000 008:00001 libstdc++.so.6.0.8

00000036796ee000      72 rw--- 00000036796ee000 000:00000   [ anon ]

00002ac25a76f000      16 rw--- 00002ac25a76f000 000:00000   [ anon ]

00002ac25a77c000      12 rw--- 00002ac25a77c000 000:00000   [ anon ]

00007fff011f8000      84 rw--- 00007ffffffe9000 000:00000   [ stack ]

00007fff013c2000      12 r-x-- 00007fff013c2000 000:00000   [ anon ]

ffffffffff600000    8192 ----- 0000000000000000 000:00000   [ anon ]

mapped: 20772K    writeable/private: 1392K    shared: 0K

Final pmap -x

Address           Kbytes     RSS   Dirty Mode   Mapping

0000000000400000       4       4       0 r-x--  a.out

0000000000500000       4       4       4 rw---  a.out

000000001b56a000    1156      12      12 rw---    [ anon ]

0000003677000000     112      96       0 r-x--  ld-2.5.so

000000367721c000       4       4       4 r----  ld-2.5.so

000000367721d000       4       4       4 rw---  ld-2.5.so

0000003677400000    1336     284       0 r-x--  libc-2.5.so

000000367754e000    2048       0       0 -----  libc-2.5.so

000000367774e000      16      16       8 r----  libc-2.5.so

0000003677752000       4       4       4 rw---  libc-2.5.so

0000003677753000      20      16      16 rw---    [ anon ]

0000003677c00000     520      20       0 r-x--  libm-2.5.so

0000003677c82000    2044       0       0 -----  libm-2.5.so

0000003677e81000       4       4       4 r----  libm-2.5.so

0000003677e82000       4       4       4 rw---  libm-2.5.so

0000003678c00000      52      16       0 r-x--  libgcc_s-4.1.2-20080825.so.1

0000003678c0d000    2048       0       0 -----  libgcc_s-4.1.2-20080825.so.1

0000003678e0d000       4       4       4 rw---  libgcc_s-4.1.2-20080825.so.1

0000003679400000     920     404       0 r-x--  libstdc++.so.6.0.8

00000036794e6000    2044       0       0 -----  libstdc++.so.6.0.8

00000036796e5000      24      24      20 r----  libstdc++.so.6.0.8

00000036796eb000      12      12      12 rw---  libstdc++.so.6.0.8

00000036796ee000      72       8       8 rw---    [ anon ]

00002ac25a76f000      16      16      16 rw---    [ anon ]

00002ac25a77c000      12      12      12 rw---    [ anon ]

00007fff011f8000      84      12      12 rw---    [ stack ]

00007fff013c2000      12       4       0 r-x--    [ anon ]

ffffffffff600000    8192       0       0 -----    [ anon ]

----------------  ------  ------  ------

total kB           20772     984     144

3 ps和pamp比较

man ps 看看它们的含义:

rss       RSS    resident set size, the non-swapped physical memory that a task has used (in kiloBytes). (alias rssize, rsz).

vsz       VSZ    virtual memory size of the process in KiB (1024-byte units). Device mappings are currently excluded; this is subject to change. (alias vsize).

简单一点说,RSS 就是这个process 实际占用的物理内存,VSZ 就是process 的虚拟内存,就是process 现在没有使用但未来可能会分配的内存大小。

其实这里的ps 出来的结果,是有点不正确的,如果把所有程序的 RSS 加起来,恐怕比你的实际内存还要大呢。为什么呢??因为 ps 的结果,RSS 那部分,是包括共享内存的。这里我用 pmap 来看看。

标签:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值