无论如何要检查C中是否有内存泄漏?

时间:2015-02-10 13:44:06

标签: c malloc free

我最近了解了memalloc()和free(),我只是想知道是否有办法正确检查是否所有的memalloc都被正确释放了?

我在这里有这个代码用于双链表的实现,并且我不清楚id是否需要遍历每个节点并释放每个p1和p2,或者一旦计数它是否做到了?:

struct s {
    int data;
    struct s *p1;
    struct s *p2;
};

void freedl(struct s *p)
{
    if(p->p1 != NULL)
    {
        printf("free %d \n", p->p1->data);
    }

    if(p->p2 != NULL)
    {
        freedl(p->p2);
    }
    else
    {
        printf("free last %d", p->data);
        free(p);
    }

}

int main(void) {

    struct s *one, *two, *three, *four, *five, *six;

    one = malloc(sizeof *one);
    two = malloc(sizeof *two);
    three = malloc(sizeof *three);
    four = malloc(sizeof *four);
    five = malloc(sizeof *five);
    six = malloc(sizeof *six);

    one->data = 1;
    one->p1 = NULL;
    one->p2 = two;

    two->data = 2;
    two->p1 = one;
    two->p2 = three;

    three->data = 3;
    three->p1 = two;
    three->p2 = four;

    four->data = 4;
    four->p1 = three;
    four->p2 = five;

    five->data = 5;
    five->p1 = four;
    five->p2 = six;

    six->data = 6;
    six->p1 = five;
    six->p2 = NULL;

    freedl(one);

    return EXIT_SUCCESS;
}

我想确保我做得对!

3 个答案:

答案 0 :(得分:2)

答案是“是”;究竟有多难取决于你所处的操作系统。

如果您使用的是Linux,Mac OS X或其中一个BSD(FreeBSD,OpenBSD,...):

(可能是Haiku)

您可以使用名为valgrind的实用程序。它是一个优秀的实用程序,专门用于(除其他事项外)确定内存泄漏。

基本用法很简单:

valgrind ./my-program

这是一个复杂的实用程序,所以我建议您查看valgrind manual以获得更高级的用法。

它实际上远不止于此,因为它可以检测到许多(但不是全部)越界访问和类似问题。它还包括可能有用的其他工具,例如callgrind用于分析代码。

请注意,valgrind由于其运作方式,会使您的程序非常慢慢运行。

任何其他操作系统(包括Windows):

不幸的是,Windows没有这样的实用工具(反正没有免费的;而且商业上花了不小的钱,最后我检查了 - 而且没有一个像valgrind&朋友可以)。

但是,您可以执行的是实现宏并在退出时手动检查:

#define malloc(size) chk_malloc(size, __FILE__, __LINE__)
#define free(ptr)    chk_free(ptr, __FILE__, __LINE__)
// etc... for realloc, calloc

...

// at start of main():
atexit(chk_report); // report problems when program exits normally

然后,您必须实施chk_mallocchk_free等。但是,如果您执行setAllocator(malloc)之类的操作,可能会出现一些“泄漏”。如果您对丢失线路信息没问题,那么您可以尝试:

#define malloc chk_malloc // chk_malloc now only takes 1 argument
#define free   chk_free
...

有一些黑客可以让你保持文件/行信息,即使这个#define,但他们会严重使问题复杂化(这将涉及基本上黑客攻击C)。

如果您不想以任何方式更改代码,您可以尝试更换这些函数(通过将stdlib替换为您自己的填充DLL),尽管您不会获得文件/行信息办法。如果编译是静态完成的,或者编译器已经用一些内在替换它(malloc不太可能,但不是不可想象的话),也可能会有问题。

实施可能非常简单,也可能很复杂,取决于您。我不知道任何现有的实现,但您可以可能在线查找内容。

答案 1 :(得分:0)

系统分配器可以通过某种方式获取统计信息(例如分配的字节数)。 (Linux上的mallinfo)。在程序开始时,您应该存储分配的字节数,最后您需要确保数字相同。如果数字不同,则可能存在内存泄漏。

发现泄漏是另一回事。像valgrind这样的工具会有所帮助。

答案 2 :(得分:0)

你可以valgrind但它可能有点慢 或者在编译器中构建的东西例如在clang中(我认为在gcc 4.9中)也有LeakSanitizer

$ cat example.c
int main()
{
    malloc(100);
    return 0;
}

$ clang -fsanitize=leak -g example.c -fsanitize=address
$ ASAN_OPTIONS=detect_leaks=1  ./a.out

=================================================================
==9038==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 100 byte(s) in 1 object(s) allocated from:
    #0 0x46c871 (/home/debian/a.out+0x46c871)
    #1 0x49888c (/home/debian/a.out+0x49888c)
    #2 0x7fea542e4ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)

SUMMARY: AddressSanitizer: 100 byte(s) leaked in 1 allocation(s).