如何检测内存泄漏?

如何检测内存泄漏?

我当前的 Ubuntu 系统似乎存在较大的内存泄漏

在报告奇怪的 Eclipse 内存错误后(https://askubuntu.com/questions/148998/eclipse-constant-different-out-of-memory-errors)今天我开始在控制台中收到“内存不足”错误消息 - 在执行一些简单的任务时,例如输入sudo -s- 甚至 -free -m

反复输入‘free -m’可以看到我的 RAM 迅速从 700M 增加到 900M,并在几秒钟内增长到 2000M 的大小(使用 释放内存后echo 3 > /proc/sys/vm/drop_caches

Eclipse 不是原因,我完全终止了该进程,但内存仍在增加。有什么方法可以检测泄漏来自哪里吗?我甚至无法再更新我的系统,因为apt-get update失败了(可能是因为内存不足)

使用Ubuntu 11.10

答案1

首先,确保有一个可用的临时文件夹,并且有足够的可用空间。以下命令会创建大小可达几 GB 的转储。

您可以使用以下命令创建一个新的 tmp 文件夹。您可能需要更改/tmp为具有足够空间的其他文件系统

TMPDIR=$(mktemp -d -t -p /tmp)

查找内存泄漏的步骤

  1. 找出导致内存泄漏的进程的 PID(htop如果可用,也可以使用例如)并将其存储在名为pid

    ps -aux
    
  2. 鉴于 PID 在变量中可用pid,您可以捕获内存消耗/proc/$pid/smaps并保存到某些文件中,例如beforeMemInc.txt

    cat /proc/$pid/smaps > $TMPDIR/beforeMemInc.txt
    
  3. 等待一段时间,直到内存消耗增加。
  4. 再次捕获/proc/$pid/smaps并保存为afterMemInc.txt

    cat /proc/$pid/smaps > $TMPDIR/afterMemInc.txt
    
  5. smaps找出 first和 2nd之间的区别smaps,例如

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

       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
    
  7. 使用 GDB 转储正在运行的进程的内存或使用以下方法获取 coredump

    gcore -o $TMPDIR/process $PID
    
  8. 我使用 gdb 在正在运行的进程中将内存转储到某个文件中。

    cd $TMPDIR
    gdb -p $pid
    dump memory memory.dump 0x2b3289290000 0x2b3289343000
    
  9. 现在,使用strings命令或hexdump -C打印memory.dump

    strings memory.dump
    

    由此您可以获得可读的信息,帮助您在源代码中找到这些字符串。

  10. 分析来源以查找泄漏。

答案2

drop_cache 技巧不会释放内存,它会重置缓存。使用附言命令,如果您想确定哪些进程使用了​​更多的内存。

例如监视常驻内存用户的前 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')

System 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         

编辑:需要传递--sort -rss给以ps获取使用内存最多的进程,否则进程列表按数字递增排序,并给出使用内存最少的进程。

答案3

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

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

内存分析

来源:Ubuntu 手册

答案4

内存状态统计也是一款不错的工具,可以显示每个块使用的内存量以及加载的库使用的内存量。虽然不是最好的工具,但值得用来收集详细信息和统计数据。

memstat -w -p pid是一个很好的命令。

相关内容