为啥 valgrind 将我的记忆报告为“肯定丢失”?

Posted

技术标签:

【中文标题】为啥 valgrind 将我的记忆报告为“肯定丢失”?【英文标题】:Why valgrind report my memory as "definitely lost"?为什么 valgrind 将我的记忆报告为“肯定丢失”? 【发布时间】:2015-06-25 21:45:07 【问题描述】:

考虑这段代码:

#include <stdlib.h>

int* alloc()

    return malloc(250 * sizeof(int));


int main()

    int i;
    int *vars[3];
    for(i = 0; i < 3; ++i) 
        vars[i] = alloc();
    

Valgrind 输出:

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

根据Valgrind's manual:

如果 --leak-check 设置得当,对于每个剩余的块, Memcheck 确定块是否可以从 根集。根集包括 (a) 通用寄存器 所有线程,以及 (b) 中已初始化、对齐、指针大小的数据字 可访问的客户端内存,包括堆栈。

据我了解,由于“肯定丢失”的内存仍然是从 main() 函数的堆栈中指向的,所以它们应该归类为“仍然可以访问”,对吧?

如果没有,我如何配置 Valgrind 以尝试从 main 的堆栈中访问内存块,以确定它们是否“仍然可以访问”?

编辑:

请不要告诉我freemain 末尾的指针,这不是我要问的。关于 Valgrind 术语中“仍然可以到达”和“绝对丢失”之间的区别,请参阅这个答案:https://***.com/a/3857638/578749

【问题讨论】:

当你的 main 结束时,你肯定失去了任何释放分配内存的机会,所以这是有道理的。在方法结束时释放三个块,错误应该会消失。 我的答案不是正确答案。我删了。 当main结束时,程序结束,反正内存会被释放。见this answer。 【参考方案1】:

main的堆栈被销毁时,也就是返回时,你的记忆肯定会丢失。因此,解决方案是不返回。

#include <stdlib.h>
int main()

    /* your code here */
    exit(0);

返回 0 或 exit(0) 的行为或 main 应该是等效的。

现在的输出是:

==5035== Memcheck, a memory error detector
==5035== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==5035== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==5035== Command: ./a.out
==5035== 
==5035== 
==5035== HEAP SUMMARY:
==5035==     in use at exit: 3,000 bytes in 3 blocks
==5035==   total heap usage: 3 allocs, 0 frees, 3,000 bytes allocated
==5035== 
==5035== LEAK SUMMARY:
==5035==    definitely lost: 0 bytes in 0 blocks
==5035==    indirectly lost: 0 bytes in 0 blocks
==5035==      possibly lost: 0 bytes in 0 blocks
==5035==    still reachable: 3,000 bytes in 3 blocks
==5035==         suppressed: 0 bytes in 0 blocks
==5035== Reachable blocks (those to which a pointer was found) are not shown.
==5035== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==5035== 
==5035== For counts of detected and suppressed errors, rerun with: -v
==5035== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

【讨论】:

以上是关于为啥 valgrind 将我的记忆报告为“肯定丢失”?的主要内容,如果未能解决你的问题,请参考以下文章

Valgrind:可能丢失可以被视为绝对丢失吗?

valgrind 使用 std::string 报告无效读取

为啥这段代码在 valgrind (helgrind) 下失败?

为啥 Linux 报告我的应用程序的内存使用量太大?

MIPS 上的 Valgrind 报告没有堆使用

Valgrind 内存泄漏报告中的时间戳不正确