绝对是C程序中丢失的内存泄漏

时间:2014-09-23 06:18:57

标签: c memory-leaks valgrind

有人能够阐明为什么Valgrind将这个程序归类为"绝对丢失:1个区块中的2个字节"内存泄漏?我知道注释行可以解决问题,但我不了解分类。根据Valgrind文档,似乎内存泄漏应归类为"间接可访问"。我也很好奇为什么这甚至被认为是内存泄漏,并希望得到解释。即使程序在main函数结束时终止,手动释放所有内容也是一种好习惯吗?

#include <stdlib.h>

struct wrapper {
  char *data;
};

char *strdup(const char *);

struct wrapper *walloc(struct wrapper *root)
{
  if (root == NULL){
    root = (struct wrapper *) malloc(sizeof(struct wrapper));
    root->data = strdup("H");
  }

  return root;
}

int main(){
  struct wrapper *root;

  root = NULL;
  root = walloc(root);

  //free(root->data);

  return 0;
}

这是Valgrind输出:

$ valgrind --leak-check=full ./leak
==26489== Memcheck, a memory error detector
==26489== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==26489== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==26489== Command: ./leak
==26489==
==26489==
==26489== HEAP SUMMARY:
==26489==     in use at exit: 2 bytes in 1 blocks
==26489==   total heap usage: 2 allocs, 1 frees, 1,790 bytes allocated
==26489==
==26489== 2 bytes in 1 blocks are definitely lost in loss record 1 of 1
==26489==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26489==    by 0x4EB79C9: strdup (in /usr/lib/libc-2.20.so)
==26489==    by 0x400542: walloc (leak.c:13)
==26489==    by 0x400542: main (leak.c:23)
==26489==
==26489== LEAK SUMMARY:
==26489==    definitely lost: 2 bytes in 1 blocks
==26489==    indirectly lost: 0 bytes in 0 blocks
==26489==      possibly lost: 0 bytes in 0 blocks
==26489==    still reachable: 0 bytes in 0 blocks
==26489==         suppressed: 0 bytes in 0 blocks
==26489==
==26489== For counts of detected and suppressed errors, rerun with: -v
==26489== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

2 个答案:

答案 0 :(得分:3)

strdup在堆上分配内存(使用malloc),因此当你不再使用这个内存时,你需要释放这个内存,就像你自己直接调用malloc一样。

即使程序完成也必须这样做,因为这是检测内存泄漏的唯一方法。当然,当程序完成时,检查任何内存泄漏的概念可能看起来有点过分,因为操作系统会自动释放所有已分配的内存,但不要忘记您的小程序是例外。通常,大多数程序在运行时会占用大量内存,如果内部存在多个内存泄漏,可能会耗尽内存或运行速度会慢得多。

即使是一个小程序也应该写得很好;否则你以后就不可能写任何大节目,因为你的坏习惯会转化为大量的编码错误。

答案 1 :(得分:2)

感谢@sharth指出我正确的方向。直接损失实际上是由Valgrind正确检测到的,但由于-O3编译完全删除了root而导致混乱。没有-O3的编译显示正确的8字节直接丢失和2字节的间接丢失。

另外,感谢@SylvainL和@Lundin的最佳实践评论。

仅供参考:修正后的Valgrind输出如下所示:

==30492== Memcheck, a memory error detector
==30492== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==30492== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==30492== Command: ./leak
==30492==
==30492==
==30492== HEAP SUMMARY:
==30492==     in use at exit: 10 bytes in 2 blocks
==30492==   total heap usage: 3 allocs, 1 frees, 1,830 bytes allocated
==30492==
==30492== 10 (8 direct, 2 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==30492==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30492==    by 0x400687: walloc (leak.c:12)
==30492==    by 0x4006C6: main (leak.c:23)
==30492==
==30492== LEAK SUMMARY:
==30492==    definitely lost: 8 bytes in 1 blocks
==30492==    indirectly lost: 2 bytes in 1 blocks
==30492==      possibly lost: 0 bytes in 0 blocks
==30492==    still reachable: 0 bytes in 0 blocks
==30492==         suppressed: 0 bytes in 0 blocks
==30492==
==30492== For counts of detected and suppressed errors, rerun with: -v
==30492== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)