Valgrind 显示 std::vector<> alloc 的次数超过 free,但没有内存泄漏
Valgrind shows std::vector<> times of alloc is more than free, but no memory leak
代码相当简单:
#include <vector>
int main() {
std::vector<int> v;
}
然后我用 Valgrind 构建并运行它:
g++ test.cc && valgrind ./a.out
==8511== Memcheck, a memory error detector
==8511== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8511== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8511== Command: ./a.out
==8511==
==8511==
==8511== HEAP SUMMARY:
==8511== in use at exit: 72,704 bytes in 1 blocks
==8511== total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
==8511==
==8511== LEAK SUMMARY:
==8511== definitely lost: 0 bytes in 0 blocks
==8511== indirectly lost: 0 bytes in 0 blocks
==8511== possibly lost: 0 bytes in 0 blocks
==8511== still reachable: 72,704 bytes in 1 blocks
==8511== suppressed: 0 bytes in 0 blocks
==8511== Rerun with --leak-check=full to see details of leaked memory
==8511==
==8511== For counts of detected and suppressed errors, rerun with: -v
==8511== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
问题有两个方面:
(1) "total heap usage"表示有1个alloc,0个free。我假设 1 alloc 是因为 std::vector 实例需要堆中的内存块。没关系;但为什么它在销毁期间不释放内存?
(2) 而且,如果它不释放它,为什么 "LEAK SUMMARY" 中没有内存泄漏?
(3) 对了,每行前面的==8511==
是什么意思? (虽然我可以在手册中查找它。你不必回答这个问题)
谢谢!
报告内存仍在被 C++ 运行时使用。你不必担心。 Valgrind 的 FAQ 有 an entry 个关于这个问题:
First of all: relax, it's probably not a bug, but a feature. Many implementations of the C++ standard libraries use their own memory pool allocators. Memory for quite a number of destructed objects is not immediately freed and given back to the OS, but kept in the pool(s) for later re-use.
(1) 正确实现的默认构造 std::vector
不会分配。 Esp 不是 72k。尝试 运行 --leak-check=full --track-origins=yes
,也许它显示了分配的来源
(2) 它说了,看:仍然可达。内存(还)没有泄漏,因为仍然有一个句柄(例如:指针)指向它。
(3)是应用程序的进程id。
您看到的 72kb 是由 C++ 运行时为其 "emergency exception-handling pool" 分配的。该池用于分配异常对象(例如 bad_alloc
异常),即使 malloc
不能再分配任何东西。我们在启动时预先分配,所以如果 malloc
内存不足,我们仍然可以抛出 bad_alloc
异常。
具体数字来自这段代码:
// Allocate the arena - we could add a GLIBCXX_EH_ARENA_SIZE environment
// to make this tunable.
arena_size = (EMERGENCY_OBJ_SIZE * EMERGENCY_OBJ_COUNT
+ EMERGENCY_OBJ_COUNT * sizeof (__cxa_dependent_exception));
arena = (char *)malloc (arena_size);
valgrind
的较新版本知道这个紧急 EH 池,并在进程退出之前调用一个特殊函数来释放它,这样你就看不到 in use at exit: 72,704 bytes in 1 blocks
。这样做是因为太多人不明白仍在使用(并且仍然可以访问)的内存不是泄漏,并且人们一直在抱怨它。所以现在 valgrind 释放了它,只是为了阻止人们抱怨。如果不是 运行 在 valgrind 下,池不会被释放,因为这样做是不必要的(无论如何 OS 都会在进程退出时回收它)。
代码相当简单:
#include <vector>
int main() {
std::vector<int> v;
}
然后我用 Valgrind 构建并运行它:
g++ test.cc && valgrind ./a.out
==8511== Memcheck, a memory error detector
==8511== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8511== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8511== Command: ./a.out
==8511==
==8511==
==8511== HEAP SUMMARY:
==8511== in use at exit: 72,704 bytes in 1 blocks
==8511== total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
==8511==
==8511== LEAK SUMMARY:
==8511== definitely lost: 0 bytes in 0 blocks
==8511== indirectly lost: 0 bytes in 0 blocks
==8511== possibly lost: 0 bytes in 0 blocks
==8511== still reachable: 72,704 bytes in 1 blocks
==8511== suppressed: 0 bytes in 0 blocks
==8511== Rerun with --leak-check=full to see details of leaked memory
==8511==
==8511== For counts of detected and suppressed errors, rerun with: -v
==8511== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
问题有两个方面:
(1) "total heap usage"表示有1个alloc,0个free。我假设 1 alloc 是因为 std::vector 实例需要堆中的内存块。没关系;但为什么它在销毁期间不释放内存?
(2) 而且,如果它不释放它,为什么 "LEAK SUMMARY" 中没有内存泄漏?
(3) 对了,每行前面的==8511==
是什么意思? (虽然我可以在手册中查找它。你不必回答这个问题)
谢谢!
报告内存仍在被 C++ 运行时使用。你不必担心。 Valgrind 的 FAQ 有 an entry 个关于这个问题:
First of all: relax, it's probably not a bug, but a feature. Many implementations of the C++ standard libraries use their own memory pool allocators. Memory for quite a number of destructed objects is not immediately freed and given back to the OS, but kept in the pool(s) for later re-use.
(1) 正确实现的默认构造 std::vector
不会分配。 Esp 不是 72k。尝试 运行 --leak-check=full --track-origins=yes
,也许它显示了分配的来源
(2) 它说了,看:仍然可达。内存(还)没有泄漏,因为仍然有一个句柄(例如:指针)指向它。
(3)是应用程序的进程id。
您看到的 72kb 是由 C++ 运行时为其 "emergency exception-handling pool" 分配的。该池用于分配异常对象(例如 bad_alloc
异常),即使 malloc
不能再分配任何东西。我们在启动时预先分配,所以如果 malloc
内存不足,我们仍然可以抛出 bad_alloc
异常。
具体数字来自这段代码:
// Allocate the arena - we could add a GLIBCXX_EH_ARENA_SIZE environment
// to make this tunable.
arena_size = (EMERGENCY_OBJ_SIZE * EMERGENCY_OBJ_COUNT
+ EMERGENCY_OBJ_COUNT * sizeof (__cxa_dependent_exception));
arena = (char *)malloc (arena_size);
valgrind
的较新版本知道这个紧急 EH 池,并在进程退出之前调用一个特殊函数来释放它,这样你就看不到 in use at exit: 72,704 bytes in 1 blocks
。这样做是因为太多人不明白仍在使用(并且仍然可以访问)的内存不是泄漏,并且人们一直在抱怨它。所以现在 valgrind 释放了它,只是为了阻止人们抱怨。如果不是 运行 在 valgrind 下,池不会被释放,因为这样做是不必要的(无论如何 OS 都会在进程退出时回收它)。