Valgrind显示std :: vector <>的次数超过了空闲时间,但没有内存泄漏

问题描述 投票:2回答:3

代码很简单:

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

(2)并且,如果它没有释放它,为什么“泄漏概要”中没有内存泄漏?

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

谢谢!

c++ memory-leaks stl valgrind
3个回答
4
投票

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

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


2
投票

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

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

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


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下运行时,池不会被释放,因为这样做是不必要的(操作系统将在进程退出时回收它)。

© www.soinside.com 2019 - 2024. All rights reserved.