如何检测内存泄漏?

分享于 

5分钟阅读

ubuntu

  繁體

echo 3 > /proc/sys/vm/drop_caches


memprof是一个用于分析内存使用情况和发现内存泄漏的工具,它可以生成配置文件,程序中每个函数分配了多少内存。此外,它还可以扫描内存,并找到已分配但不再引用的块。

memprof通过预加载库来重写C库的内存分配函数,不需要重新编译程序。

memprof


如果要标识哪些进程使用了多少内存,请使用ps命令。

例如,监视驻留内存用户的前15个列表。


$ watch"ps --sort -rss -eo pid,pmem,rss,vsz,comm | head -16"


 PID %MEM RSS VSZ COMMAND


 2590 13.4 136892 825000 firefox


 1743 10.7 109020 300780 Xorg


 2067 8.5 86764 1118140 unity-2d-shell


 3307 4.1 42560 627780 unity-2d-spread


 2068 2.9 29904 617644 unity-2d-panel


 2092 2.5 25524 1291204 nautilus


 2457 1.9 20292 530276 gnome-terminal


 2351 1.9 20016 821488 unity-scope-vid


 2161 1.9 19476 531968 unity-panel-ser


 2034 1.7 18256 759716 gnome-settings-


 2074 1.5 16176 518016 nm-applet


 2273 1.5 15452 580416 unity-lens-vide


 2051 1.4 15112 524260 metacity


 2395 1.2 12836 407336 update-notifi



也可以检查共享内存保留,但你只知道谁是段的所有者。

Pmap分配:


$ ls -l /run/shm


total 272


-r-------- 1 ed ed 67108904 Nov 29 18:17 pulse-shm-1884617860


-r-------- 1 lightdm lightdm 67108904 Nov 29 18:11 pulse-shm-2352897759


-r-------- 1 ed ed 67108904 Nov 29 18:12 pulse-shm-3444873503


-r-------- 1 ed ed 67108904 Nov 29 18:12 pulse-shm-3485341848


-r-------- 1 lightdm lightdm 67108904 Nov 29 18:11 pulse-shm-535843976


-r-------- 1 ed ed 67108904 Nov 29 19:12 pulse-shm-789046959


-r-------- 1 ed ed 67108904 Nov 29 18:38 pulse-shm-863909656



$ df /run/shm 


Filesystem 1K-blocks Used Available Use% Mounted on


none 509332 272 509060 1% /run/shm



请注意,保留分配比实际分配的页面(df 'used ')高得多

系统V分配:


$ ipcs -m 



------ Shared Memory Segments --------


key shmid owner perms bytes nattch status 


0x00000000 294912 ed 700 122880 2 dest 


0x00000000 327681 ed 700 4823040 2 dest 


0x00000000 491522 ed 600 393216 2 dest 


0x00000000 589827 ed 700 4578120 2 dest 


0x00000000 425988 ed 700 27852 2 dest 


0x00000000 458757 ed 600 393216 2 dest 




以下是找到泄漏内存的步骤:

  • 找出导致内存泄漏的进程的PID。

     
    ps -aux
    
    
    
    
  • 捕获/proc/PID/smaps,并保存到一些文件,如BeforeMemInc.txt

  • 等待内存增加
  • 再次捕获/proc/PID/smaps,并保存它有afterMemInc.txt
  • 找出第一个smaps和第二个smaps之间的区别。

    diff -u beforeMemInc.txt afterMemInc.txt 
  • 记下内存增加的地址范围,例如:

    
     beforeMemInc.txt afterMemInc.txt
    
    
    ---------------------------------------------------
    
    
    2b3289290000-2b3289343000 2b3289290000-2b3289343000 #ADDRESS
    
    
    Shared_Clean: 0 kB Shared_Clean: 0 kB 
    
    
    Shared_Dirty: 0 kB Shared_Dirty: 0 kB
    
    
    Private_Clean: 0 kB Private_Clean: 0 kB
    
    
    Private_Dirty: 28 kB Private_Dirty: 36 kB 
    
    
    Referenced: 28 kB Referenced: 36 kB
    
    
    Anonymous: 28 kB Anonymous: 36 kB #INCREASE MEM
    
    
    AnonHugePages: 0 kB AnonHugePages: 0 kB
    
    
    Swap: 0 kB Swap: 0 kB
    
    
    KernelPageSize: 4 kB KernelPageSize: 4 kB
    
    
    MMUPageSize: 4 kB MMUPageSize: 4 kB
    
    
    Locked: 0 kB Locked: 0 kB
    
    
    VmFlags: rd wr mr mw me ac VmFlags: rd wr mr mw me ac
    
    
    
    
  • 使用GDB转储正在运行的进程的内存,或者使用gcore -o process获取coredump

  • 在运行进程中使用gdb将内存转储到某个文件。

    
    gdb -p PID
    
    
    dump memory ./dump_outputfile.dump 0x2b3289290000 0x2b3289343000
    
    
    
    
  • 现在,使用strings命令或hexdump -C打印dump_outputfile.dump

    
    strings outputfile.dump
    
    
    
    
  • 获得可读的形式,可以在源代码中找到这些字符串。

  • 分析你的源头找到漏洞。



  • 相关文章