Valgrind显示std :: vector<> alloc的次数超过了free,但没有内存泄漏

时间:2017-08-06 06:56:37

标签: c++ memory-leaks stl valgrind

代码非常简单:

#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)&#34;总堆使用量&#34;表示有1个alloc和0个free。我假设1 alloc是因为std :: vector实例需要堆中的内存块。没关系;但为什么在毁灭期间它没有释放记忆?

(2)并且,如果它没有释放它,为什么没有内存泄漏&#34; LEAK SUMMARY&#34;?

(3)顺便说一句,每行前==8511==是什么意思? (不过,我可以在手册中查一查。你不必回答这个问题)

谢谢!

3 个答案:

答案 0 :(得分:4)

C ++运行时仍在使用报告的内存。你不必担心它。关于这个问题,Valgrind的FAQ有an entry

  

首先:放松,这可能不是一个错误,而是一个功能。许多C ++标准库的实现都使用自己的内存池分配器。许多被破坏对象的内存不会立即被释放并返回给操作系统,而是保存在池中以供以后重复使用。

答案 1 :(得分:2)

(1)正确实现的默认构造std::vector没有分配。 Esp不是72k。尝试使用--leak-check=full --track-origins=yes运行,也许它会显示分配的来源

(2)它说,看到:仍然可以到达。内存尚未泄漏,因为它仍然是一个指向它的句柄(例如:一个指针)。

(3)它是应用程序的进程ID。

答案 2 :(得分:1)

您所看到的72kb是由C ++运行时为其“紧急异常处理池”分配的。该池用于分配异常对象(例如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);

请参见https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/libsupc%2B%2B/eh_alloc.cc;h=005c28dbb1146c28715ac69f013ae41e3492f992;hb=HEAD#l117

较新版本的valgrind知道此紧急EH池,并在进程退出之前立即调用一个特殊函数将其释放,以使您看不到in use at exit: 72,704 bytes in 1 blocks。这样做是因为太多的人不了解仍在使用(并且仍然可以访问)的内存并不是泄漏,并且人们一直抱怨它。因此,现在valgrind释放了它,只是为了阻止人们抱怨。当不在valgrind下运行时,不会释放该池,因为这样做是不必要的(无论如何,该进程退出时,操作系统都会对其进行回收)。