2014-09-23 30 views
6

有人能够阐明为什么Valgrind将此程序归类为“绝对丢失:2个字节的1块”内存泄漏?我了解评论线可以解决问题,但我不了解分类。根据Valgrind文档,内存泄漏应该被分类为“间接可达”。我也很好奇,为什么这甚至被认为是内存泄漏,并会赞赏解释。即使程序在main函数的末尾终止,是否手动释放所有内容是一种好的做法?在C程序中肯定会失去内存泄漏

#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

“它是很好的做法,即使该程序在主函数结束时终止手动自由的一切吗?”是的,即使操作系统释放内存,也要这样做。 'free()'可以暴露程序中的错误,否则很难找到它们。在完成分配代码后直接执行解除分配是一种好习惯。 – Lundin 2014-09-23 06:35:24

+2

我没看到这个。我看到8个字节肯定丢失('root'),2个字节间接丢失('root-> data')。你能发布valgrind的完整输出吗? – 2014-09-23 06:38:07

+0

你应该'#include ',因为编译器可以用'strdup'(和[GCC](http://gcc.gnu.org/)有时候做)“神奇”的东西 – 2014-09-23 06:42:15

回答

2

感谢@sharth指引我在正确的方向。 Valgrind实际上正确地检测到了直接损失,但是由于-O3编译完全删除了root,所以令人困惑。编译没有-O3显示8字节的合适的直接损失和2字节的间接损失。

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

FYI:校正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) 
3

的strdup(使用malloc),因此你需要的时候它不再像使用你自己的人来释放此内存堆上分配内存直接调用malloc。

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

即使是一个小程序也应该写得很好;否则以后你不可能再编写任何大型程序,因为你的不良习惯会导致大量的编码错误。

+0

感谢您的回复。为什么Valgrind在字符串嵌套在结构中时将其报告为直接泄漏?另外,为什么Valgrind不会抱怨释放分配给'root'的内存? – 2014-09-23 17:06:48

+0

对不起,我不使用Valgrind,因此我不知道它使用的各种定义。也许分配给root用户的内存就是它所称的“损失记录”,但您应该查看文档或者在专门针对Valgrind的论坛中提问,或者在此处专门写关于Valgrind的另一个问题。 – SylvainL 2014-09-23 17:26:40