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

how*_*rks 26 c memory-leaks gdb

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

小智 17

我认为memleax正是您想要的。

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

它适用于 GNU/Linux 和 FreeBSD。

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

== 编辑 ==

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

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

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

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

  • 我保证 memleax 是一个非常有用的工具,可以监控任何明显的泄漏。[输出摘要非常有效](http://i.imgur.com/lL4Qe7i.png)。如果我有处理能力手动完成,我几乎会写它们。谢谢你 (2认同)

小智 17

以下是几乎可以保证找到内存泄漏的步骤:

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

    ps -aux
    
    Run Code Online (Sandbox Code Playgroud)
  2. 捕获/proc/PID/smaps并保存到某个文件中,例如BeforeMemInc.txt.

  3. 等到内存增加。
  4. 再次捕获/proc/PID/smaps并保存afterMemInc.txt
  5. 找到 firstsmaps和 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
    
    Run Code Online (Sandbox Code Playgroud)
  7. 使用 GDB 转储正在运行的进程的内存或使用获取核心转储 gcore -o process

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

    gdb -p PID
    dump memory ./dump_outputfile.dump 0x2b3289290000 0x2b3289343000
    
    Run Code Online (Sandbox Code Playgroud)
  9. 现在,使用strings命令或hexdump -C打印dump_outputfile.dump

    strings outputfile.dump
    
    Run Code Online (Sandbox Code Playgroud)
  10. 您可以获得可读的形式,您可以在其中将这些字符串定位到您的源代码中。

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

  • strings 命令没有给我任何提示在哪里查看我的源文件。对我来说,我只看到一些垃圾字符串。 (4认同)

Use*_*ess 6

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

在 OpenBSD 上,您可以尝试malloc stats

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


Chr*_*tti 0

我认为如果不直接在源代码中程序启动后提供对分配监视的支持,你就不走运了。我能想到的原因有两个:

  • 堆检查器在程序开始时初始化。有些提供了调整确切时间的能力,但是启动它们的环境变量必须在程序运行时设置。这是因为他们会观察以确保每个分配都有相应的释放,否则他们会错过一些。
  • 堆检查通常需要操作系统提供提升的权限或挂钩。如果在程序启动时未提供这些挂钩,则堆检查器无法利用它们。我不相信操作系统在相关程序启动后提供这些权限。

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