【问题标题】:Why does Valgrind not report any issue after not freeing malloc'd memory?为什么 Valgrind 在不释放 malloc 的内存后不报告任何问题?
【发布时间】:2020-02-10 16:42:47
【问题描述】:

我试图弄清楚为什么 Valgrind 不发出任何警告,即使在下面的代码中,malloc 之后没有 free

#include "stdlib.h"
#include "string.h"

char* ptr;

int main (int argc, char *argv[]) {
    ptr = static_cast<char*>(malloc(5 * sizeof(char)));
    strcpy(ptr, "test");
}

是否有某种我不知道的“自动免费”或者我错过了什么?

谢谢。

【问题讨论】:

  • 只是猜测,但是如果您分配内存并将其存储在全局中,除非您将指针替换为其他内容,否则它永远不会泄漏,否则您始终可以访问它。 valgrind 能否检测到后一种情况是另一回事。
  • 可能是这种情况。我认为到达main 的末尾将是将该内存标记为丢失的一个很好的理由,即使此时执行已经结束。
  • Valgrind 肯定会知道这个内存并将其报告为still reachable。您的程序没有内存泄漏,因为它没有丢失对已分配内存的最后引用。 main 退出后,程序还没有完全终止。在 C 中,库中有 atexit 处理程序可以调用和清理,C++ 有全局析构函数。

标签: c++ malloc valgrind free


【解决方案1】:

它确实报告了该问题,但要查看它,您需要使用 --leak-check=full --show-leak-kinds=all 选项运行 Valgrind:

$ valgrind --leak-check=full --show-leak-kinds=all ./a.out
==317235== Memcheck, a memory error detector
==317235== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==317235== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==317235== Command: ./a.out
==317235== 
==317235== 
==317235== HEAP SUMMARY:
==317235==     in use at exit: 5 bytes in 1 blocks
==317235==   total heap usage: 2 allocs, 1 frees, 72,709 bytes allocated
==317235== 
==317235== 5 bytes in 1 blocks are still reachable in loss record 1 of 1
==317235==    at 0x483980B: malloc (vg_replace_malloc.c:309)
==317235==    by 0x40113E: main (1.cpp:7)
==317235== 
==317235== LEAK SUMMARY:
==317235==    definitely lost: 0 bytes in 0 blocks
==317235==    indirectly lost: 0 bytes in 0 blocks
==317235==      possibly lost: 0 bytes in 0 blocks
==317235==    still reachable: 5 bytes in 1 blocks
==317235==         suppressed: 0 bytes in 0 blocks
==317235== 
==317235== For lists of detected and suppressed errors, rerun with: -s
==317235== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

即使你在没有任何选项的情况下运行 Valgrind,你也可以在 HEAP 总结部分看到问题:

==317235==     in use at exit: 5 bytes in 1 blocks

但没有更多细节。

【讨论】:

  • 谢谢,它也对我有用。一开始我只尝试了--leak-check=full,但显然还不够。
  • 我还注意到另一个警告:==2937==72,704 bytes in 1 blocks are still reachable in loss record 1 of 1 ==2937==at 0x483577F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) [...some traces...] ==2937==by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.28.so) 我假设这不是我的错,是吗?
  • 是的,这可能是 GCC 故障,请参阅 stackoverflow.com/q/31775034/72178
【解决方案2】:

内存泄漏意味着指向已分配内存的指针值丢失。一旦值丢失,就不能再释放内存了。

静态指针的生命周期是整个进程的执行。因此指针值永远不会丢失,因为它始终被存储,并且在程序的任何时候都不会出现指针无法释放的情况。

Valgrind documentation 将此类内存分类为:

“仍然可以访问”。这涵盖了上面的案例 1 和 2(对于 BBB 块)。找到指向该块的起始指针或起始指针链。由于该块仍然被指向,程序员至少在原则上可以在程序退出之前释放它。 “仍然可以访问”的块很常见,可以说不是问题。因此,默认情况下,Memcheck 不会单独报告此类块。


是否有某种“自动免费”

不是在调用free 的意义上,但是一旦程序停止,它就不再存在并且它的分配是无关紧要的。

【讨论】:

    猜你喜欢
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 2012-01-27
    • 2020-09-17
    • 2015-06-12
    • 2014-02-19
    • 2019-03-14
    • 1970-01-01
    相关资源
    最近更新 更多