如何找到正在运行的进程的内存泄漏?


19

有没有办法,我可以找到正在运行的进程的内存泄漏?我可以使用Valgrind在进程开始之前查找内存泄漏。我可以使用GDB将其附加到正在运行的进程。如何调试正在运行的进程的内存泄漏?


Valgrind非常有用,我什至可以称之为直观。
user400344 '16

Answers:


13

这几乎是保证找到谁正在泄漏内存的步骤:

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

    ps -aux
  2. 捕获/proc/PID/smaps并保存到类似的文件中BeforeMemInc.txt

  3. 等到内存增加。
  4. 再次捕获/proc/PID/smaps并保存afterMemInc.txt
  5. 找到first smaps和2nd 之间的差异smaps,例如

    diff -u beforeMemInc.txt 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 process

  8. 我在运行过程中使用gdb将内存转储到某些文件。

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

    strings outputfile.dump
  10. 您将获得可读的表格,可以在其中将这些字符串定位到源代码中。

  11. 分析您的来源以查找泄漏。


12

我认为memleax正是您想要的。

它通过附加运行中的进程来调试其内存泄漏,而无需重新编译程序或重新启动目标进程。非常方便,适合生产环境。

它适用于GNU / Linux和FreeBSD。

注意:我是作者,欢迎任何建议

==编辑==

我写了另一个工具libleak,它通过LD_PRELOAD挂钩内存功能。

也无需修改目标程序。尽管必须使用LD_PRELOAD重新启动进度,但是可以在运行期间启用/禁用检测。

由于没有信号陷阱,因此对性能的影响要小得多。

与类似的工具(例如mtrace)相比,它在可疑的内存泄漏点打印完整的调用堆栈。


1
我保证memleax是监视任何明显泄漏的非常有用的工具。的输出摘要是令人惊讶地有效。如果我具有手动处理的能力,几乎就像我会写它们一样。谢谢你
sehe

6

在Linux上,可以在程序中启用mtrace,但这是代码更改。

在OpenBSD上,您可以尝试使用malloc stats

Google的泄漏检查程序也可能值得一看,与mtrace不同,您可以使用它LD_PRELOAD来避免重新编译。


0

我认为,在直接在源代码中启动程序后,如果不提供对分配监视的支持,那么您很不幸。我可以想到以下两个原因:

  • 程序开始时,堆检查器会初始化。有些提供了调整精确时间的功能,但是启动它们的环境变量必须在程序运行时进行设置。这是因为他们注意确保每个分配都有相应的解除分配,否则他们会错过一些分配。
  • 堆检查通常需要操作系统提供提升的特权或挂钩。如果在程序启动时未提供这些钩子,则堆检查器将无法利用它们。我不认为操作系统在启动有问题的程序后会提供这些特权。

但是,如果您的程序在虚拟机中运行,则该环境可能会提供监视分配的支持。我知道Java有几个分配和垃圾收集监视工具(例如visualVM),它们附接到正在运行的程序或VM。


0

IBM的Purify可能是所有工具中最古老,最先进的工具。它将在代码中标记行号,从而导致内存泄漏。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.