GCC内存泄漏检测相当于Microsoft crtdbg.h?

时间:2009-11-19 05:38:00

标签: c++ c xcode gcc memory-leaks

在Visual Studio中使用Microsoft MSVC编译器开发通用C ++库多年后,我们现在将其移植到Linux / Mac OS X(为我们祈祷)。我已经习惯了并且非常喜欢MSVC中简单的内存泄漏检测机制:

#ifdef DEBUG
    #define _CRTDBG_MAP_ALLOC
    #define NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
    #include <stdlib.h>
    #include <crtdbg.h>
#else
    #define NEW   new
#endif

使用此NEW宏完成每个内存分配。每当使用我们的库的进程终止时,任何内存泄漏(尚未解除分配的块)都会在控制台上与最初分配内存的文件和行#一起报告。

关于这个我喜欢的部分是我不必主动“运行性能工具”或以其他方式表明我正在寻找泄漏。每次进程终止时,都会在正常的开发过程中向我报告泄漏。

现在我们正在转向GCC世界,我发现内存泄漏检测工具,其中许多非常复杂,需要我明确表明我处于泄漏搜索模式。我的IDE是Xcode,我已经研究了一些分配/泄漏检测工具(比如Instruments和MallocDebug),但我承认我还没有花时间完全了解它们。事实上,我实际上必须提前说明我正在寻找泄漏,而不是自动提醒它,这让我不知所措。

我正在使用Xcode 3.2,我听说现在已经与静态分析工具进行了很好的集成,但我再次没有考虑过这个问题。我正在寻找一些关于我的选择的想法。 GCC和/或Xcode中是否有类似的机制?是否有一个简单的第三方库或工具可以执行我所熟悉和喜爱的基本功能?或者我应该吸收它并学习新的做事方式?

7 个答案:

答案 0 :(得分:19)

您可以使用多种选项。

首先,最常见的是,您可以使用Valgrind等工具运行您的应用程序。这应该指向一些内存滥用,例如NULL指针读取和写入以及内存泄漏。 Valgrind套件中提供了许多工具,因此请务必查看它们。

其次,您始终可以使用使用LD_PRELOAD技巧的库。基本上,LD_PRELOAD技巧允许DLL注入,这意味着可以创建工具来帮助跟踪应用程序中的内存使用情况,而无需进行任何更改。您会发现dmallocefence等工具在他们提供的调试工具中非常广泛。

最后,最近的GCC版本包括一个名为Mudflap的工具。这基本上使用函数检测来包围与dmalloc,efence和Valgrind相同的内存函数的调用。该程序将明显变慢,并且可以在运行时进行调整,尽管它看起来仍然具有很大的潜力。

我已经使用了所有三个并且发现Valgrind非常有用。我一直对使用Mudflap非常感兴趣,尽管我还没有。但

答案 1 :(得分:15)

你应该看看“Cross-Platform Memory Leak Detector”,看起来非常类似于crtdbg.h技术。

答案 2 :(得分:9)

您可能还会发现MALLOC_CHECK_环境变量很有用。

来自malloc(3)手册页:

  

最近版本的Linux libc(晚于5.4.23)和glibc(2.x)包含一个malloc()实现,它可以通过环境变量进行调整。当设置MALLOC_CHECK_时,使用一个特殊的(效率较低的)实现,它被设计为容忍简单错误,例如使用相同参数的free()的双重调用,或者单个字节的溢出(off-by-one bug) )。但是,并非所有此类错误都可以得到保护,并且可能导致内存泄漏。如果MALLOC_CHECK_设置为0,则会自动忽略任何检测到的堆损坏;如果设置为1,则在stderr上打印诊断消息;如果设置为2,则立即调用abort(3);如果设置为3,则在stderr上打印诊断消息并中止程序。使用非零MALLOC_CHECK_值可能很有用,因为否则崩溃可能会在很晚之后发生,因此很难找到导致问题的真正原因。

答案 3 :(得分:4)

也许你可以使用Boehm garbage collector作为泄漏检测工具:

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

来自网站:

#include "leak_detector.h"

main() {
    int *p[10];
    int i;
    /* GC_find_leak = 1; for new collector versions not     */
    /* compiled with -DFIND_LEAK.               */
    for (i = 0; i < 10; ++i) {
    p[i] = malloc(sizeof(int)+i);
    }
    for (i = 1; i < 10; ++i) {
    free(p[i]);
    }
    for (i = 0; i < 9; ++i) {
    p[i] = malloc(sizeof(int)+i);
    }
    CHECK_LEAKS();
}   

(通过stderr收到通知)

答案 4 :(得分:3)

我不知道有什么“内置”可以做你所描述的内容,但似乎并不是很难“推出自己的”版本。你只需要你的调试new来记录指针,文件和行在map<void*, AllocationInfo>中,其中键是分配的指针,值(AllocationInfo)将是一个包含文件名,行号,您还需要定义一个自定义删除操作符,用于检查映射以查找要删除的指针。如果找到,则该条目将从地图中删除。然后在进程关闭时,您将发出地图的内容。

我找到了a page where someone describes their own home-grown system that works like this

答案 5 :(得分:3)

当我们开始移植到Mac时,我遇到了同样的问题。 “使用性能工具运行 - &gt;泄漏”是我发现的唯一一个,我对此感到兴奋......至少与CRTDEBUG相比。我知道有一些选项(正如其他人所描述的那样),但最终由于我们是多平台,我们正在使用Windows来查找泄漏。

因为你提到了静态分析仪。我们花了一些时间试图弄清楚它是否正常运行,直到我们发现它只有C而不是C ++

答案 6 :(得分:0)

一段时间以来,clang和gcc都支持某些“消毒器”,包括泄漏消毒器。在编译期间启用该代码后,编译器将对代码进行检测,以在运行时执行相应的检查。在gcc上,使用“ -fsanitize = leak”启用了泄漏清理程序。参见https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html