我有一个用 C++ 编写的简单程序,它构建在以下配置中:
libstdc++
libc++
我使用 valgrind 运行两个版本,如下所示:
valgrind --leak-check=full --show-reachable=yes --track-origins=yes --log-file=test_program.log -v ./test_program
libstdc++
版本运行并不会导致内存泄漏:
==
== HEAP SUMMARY:
== in use at exit: 0 bytes in 0 blocks
== total heap usage: 24,813,106 allocs, 24,813,106 frees, 51,325,970,073 bytes allocated
==
== All heap blocks were freed -- no leaks are possible
==
== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
但是,当运行
libc++
时,它显示内存泄漏:
==434036== HEAP SUMMARY:
==434036== in use at exit: 16 bytes in 1 blocks
==434036== total heap usage: 317,709,577 allocs, 317,709,576 frees, 645,827,127,171 bytes allocated
==434036==
==434036== Searching for pointers to 1 not-freed blocks
==434036== Checked 401,408 bytes
==434036==
==434036== 16 bytes in 1 blocks are still reachable in loss record 1 of 1
==434036== at 0x484DA83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==434036== by 0x49A365F: ??? (in /usr/lib/llvm-14/lib/libc++abi.so.1.0)
==434036== by 0x49A24E9: __cxa_get_globals (in /usr/lib/llvm-14/lib/libc++abi.so.1.0)
==434036== by 0x49A53F6: __cxa_throw (in /usr/lib/llvm-14/lib/libc++abi.so.1.0)
==434036== by 0x2EE7B3: goal::details::special_node<double>::value() const (in workspace/goal/goal_test)
==434036== by 0x2DC349: goal::details::caller_node<double>::value() const (in workspace/goal/goal_test)
==434036== by 0x50AC40: double goal::details::arg_node<double>::process<main_node<double> > const&) (in workspace/goal/goal_test)
==434036== by 0x45A79C: bool execute_test_base<double>() (in workspace/goal/goal_test)
==434036== by 0x2322A0: main (in workspace/goal/goal_test)
==434036==
==434036== LEAK SUMMARY:
==434036== definitely lost: 0 bytes in 0 blocks
==434036== indirectly lost: 0 bytes in 0 blocks
==434036== possibly lost: 0 bytes in 0 blocks
==434036== still reachable: 16 bytes in 1 blocks
==434036== suppressed: 0 bytes in 0 blocks
==434036==
==434036== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我有两个进一步的程序版本:
libstdc++
一起使用/链接 与 ASAN/LSAN/UBSAN/TSAN
libc++
一起使用/链接 与 ASAN/LSAN/UBSAN/TSAN
运行它们时,它们都不会触发消毒剂错误或警告。
使用的编译器:
仅当与 libc++ 链接时才在两个编译器上观察到 valgrind 泄漏。
问题: valgrind 的泄漏是否可能是误报?还可以采取哪些措施来验证其合法性?
简单的规则。不要欺骗自己,认为可能存在误报。这几乎总是只是一厢情愿和确认偏见。
Valgrind memcheck 确实会产生一些误报,但数量很少。泄漏检测是一项“简单”的工作,因此误报率基本上为零。
Memcheck 可以比消毒剂更好地进行泄漏检测,因为它可以完整地查看来宾 exe 的执行情况,从第一条指令到最后一条指令。我不是消毒剂专家,但我想消毒剂代码只能在第一个全局构造函数执行时启动。
正如评论中所说,如果你的 exe 抛出一个以 std::terminate 结尾的异常,那么像 atexit cleanup 这样的事情就不会被执行。仅当 exe 执行干净退出时,泄漏检测才有意义。