22

我首先寻找现有的答案,发现Valgrind是大家最喜欢的 linux 上内存泄漏调试工具。不幸的是, Valgrind似乎不适用于我的目的。我将尝试解释原因。

约束:

  • 泄漏仅在客户的环境中重现。由于某些法律限制,我们必须使用现有的二进制文件。没有重建。
  • 在常规环境中,我们的应用程序消耗约 10% 的 CPU。比如说,我们可以容忍高达 10 倍的 CPU 使用率增加。使用默认memcheck设置的Valgrind 会更糟糕地使我们的应用程序长时间无响应。

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

这是我考虑过的工具/方法

  • Valgrind-memcheck–massif工具它们做的比需要的多得多(比如扫描整个进程内存以查找每个分配指针),它们太慢了,而且它们仍然不能完全满足我
    的需要(转储按计数排序的调用堆栈) ,所以我将不得不编写一些脚本来解析输出
  • dmalloc库 (dmalloc.com) 需要新的二进制文件
  • LeakTracer ( http://www.andreasen.org/LeakTracer/ ) 仅适用于 C++ new/delete (我也需要malloc/free ),没有按堆栈分组和排序功能
  • 使用 LD_PRELOAD 机制将工具自己实现为 .so 库(使用 LD_PRELOAD 机制覆盖“malloc”)考虑到我的 Linux 编码技能,这至少需要一周时间,感觉就像发明了一辆自行车。

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

4

8 回答 8

17

GNU libc 有内置的 malloc 调试:

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

使用 LD_PRELOADmtrace()从您自己的 .so 调用:

#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

于 2013-08-27T02:03:06.347 回答
5

我想宣传我刚刚宣布的 heaptrack 实用程序,它应该正是您当时正在寻找的东西。你可以在这里找到更多信息:http: //milianw.de/blog/heaptrack-a-heap-memory-profiler-for-linux

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

我很想得到更多关于它的反馈,所以试试吧!

于 2014-12-03T10:38:45.613 回答
5

memleax应该适合你。

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

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

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

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

于 2016-12-09T02:03:32.113 回答
2

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

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

于 2013-08-27T12:39:32.690 回答
1

@glagolig,

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

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

克里斯·戈特布拉斯

Rogue Wave Software TotalView 首席产品经理

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

于 2013-08-29T20:48:32.377 回答
1

令人惊讶的是,我在开源域中找不到像 Microsoft 的 UMDH 之类的东西,也无法立即下载。(我还查看了Google Heap Leak Checker,但它更像 Valgrind 而不是 UMDH)。因此,我最终使用malloc 检测项目作为参考点自己编写了该工具:

https://github.com/glagolig/heapwatch

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

于 2013-09-21T21:53:21.250 回答
0

有一个名为 chap 的免费开源工具,可以满足您的大部分需求。它特别不会给你堆栈跟踪,但它是一个非常轻量级的工具,因为它根本不需要任何仪器。您所需要的只是能够抓住相关流程的实时核心,在您认为该流程已经出现错误的点上(因此您认为它已经泄漏或太大或其他)。

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

于 2018-05-29T17:55:11.330 回答
0

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

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

于 2019-07-30T22:48:30.413 回答