Linux上的轻量级内存泄漏调试

时间:2013-08-27 01:52:25

标签: c++ c linux valgrind

我首先查找了现有的答案,并发现 Valgrind 是每个人最喜欢的linux上内存泄漏调试工具。不幸的是, Valgrind 似乎不适用于我的目的。我会尝试解释原因。

约束:

  • 泄漏仅在客户的环境中重现。由于一定的 法律限制我们必须使用现有的二进制文件。没有重建。
  • 在常规环境中,我们的应用程序消耗~10%的CPU。说,我们可以 容忍高达10倍的CPU使用量增加。带有默认 memcheck Valgrind 设置做得更糟,使我们的应用程序长时间没有响应 一段时间。

我需要的是相当于Microsoft的 UMDH :为每个堆分配打开堆栈跟踪,然后在某个时间点转储按堆栈分组的所有分配,并按分配计数按降序排序。我们的应用程序在Windows和Linux平台上提供,因此我知道在 UMDH 下的Windows上的性能仍然可以容忍。

以下是我考虑的工具/方法

  • Valgrind -memcheck -massif 工具他们做的远远超过了需要(比如扫描每个分配的整个进程内存) 指针),它们太慢了,它们仍然没有完全按照我的意思 需要(转储按计数排序的callstack),所以我将不得不写一些 解析输出的脚本
  • dmalloc 库(dmalloc.com)需要新的二进制文件
  • LeakTracer(http://www.andreasen.org/LeakTracer/)仅适用于C ++ new / delete (我还需要 malloc / free ),没有逐个堆栈 和排序功能
  • 使用LD_PRELOAD将自己实现为.so库 机制 (Overriding 'malloc' using the LD_PRELOAD mechanism) 考虑到我的Linux编码技巧,这至少需要一周的时间 就像发明一辆自行车一样。

我错过了什么吗?是否有任何轻量级的 Valgrind 选项或现有的LD_PRELOAD工具?

8 个答案:

答案 0 :(得分:14)

GNU libc内置了malloc调试功能:

http://www.gnu.org/software/libc/manual/html_node/Allocation-Debugging.html

使用LD_PRELOAD从您自己的.so:

中调用mtrace()
#include <mcheck.h>
static void prepare(void) __attribute__((constructor));
static void prepare(void)
{
    mtrace();
}

用以下内容编译:

gcc -shared -fPIC dbg.c -o dbg.so

使用以下命令运行:

export MALLOC_TRACE=out.txt
LD_PRELOAD=./dbg.so ./my-leaky-program

稍后检查输出文件:

mtrace ./my-leaky-program out.txt

你会得到类似的东西:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000001bda460     0x96  at /tmp/test/src/test.c:7

当然,您可以自由编写自己的malloc挂钩来转储整个堆栈(如果您认为有帮助,可以调用backtrace()。)

如果您在某处保留了二进制文件的调试信息(例如,二进制文件内置了一些调试信息,或者您执行了objcopy --only-keep-debug my-leaky-program my-leaky-program.debug),则可以获取行号和/或函数名称。


另外,您可以尝试使用Boehm的GC,它也可以作为检漏仪使用:

http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html

答案 1 :(得分:4)

我想宣传我刚宣布的堆栈实用工具,这应该就是你在那里寻找的东西。您可以在此处找到更多信息:http://milianw.de/blog/heaptrack-a-heap-memory-profiler-for-linux

与你的heapwatch工具相比,性能应该要好得多,因为我使用libunwind和更高版本的libbacktrace来延迟使用DWARF调试信息的回溯注释。

我希望得到更多有关它的反馈,所以试一试!

答案 2 :(得分:2)

MemoryScape 可以满足您的需求。这是 TotalView 调试器附带的动态内存调试工具。

http://www.roguewave.com/products/memoryscape.aspx

答案 3 :(得分:2)

memleax应该适合你。

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

它仅对malloc / free()调用进行TRAP,因此它应该比Vagrild带来更少的性能影响。

适用于GNU / Linux-x86_64和FreeBSD-amd64。

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

答案 4 :(得分:1)

@glagolig,

是的,MemoryScape可以按堆栈位置对分配进行分组。

您能获得评估版吗?假设您使用的电子邮件地址看起来不像机器人,您应该很快就会收到我们的回复。如果没有,或者您遇到技术问题,请给我一个喊叫或联系我们的技术支持团队。

Chris Gottbrath

Rogue Wave Software的TotalView首席产品经理

电子邮件:名字。姓氏(at)roguewave。 COM

答案 5 :(得分:1)

令人惊讶的是,我无法在开源域中找到类似Microsoft的UMDH或可立即下载的内容。 (我也看了Google Heap Leak Checker,但它更像是Valgrind,而不是UMDH)。所以我最终使用malloc instrumentation项目作为参考点来编写工具:

https://github.com/glagolig/heapwatch

该工具有许多限制,但它对我的目的来说效果很好。

答案 6 :(得分:0)

有一个名为chap的免费开源工具可以完成您想要的大部分工作。它特别不会给你堆栈痕迹,但它是一个非常轻量级的工具,因为它根本不需要任何仪器。您所需要的只是能够抓住相关过程的实时核心,在此时您认为该过程已经显示出错误(因此您认为它已泄露或过大或其他任何原因)。

有关详细信息,请参阅https://github.com/vmware/chap

答案 7 :(得分:0)

您还可以考虑使用Google的gperftools,该工具具有可通过LD_PRELOAD加载的堆分析器。您还可以将其tcmalloc和泄漏检查器链接到您的二进制文件中,并仅在需要时启用它们。

有关详细信息,请参见https://github.com/gperftools/gperftools