c++ - 当程序退出时,C++库实现如何分配内存但不释放内存?

标签 c++ memory-management libstdc++

代码很简单:

#include <vector>
int main() {
    std::vector<int> v;
}

然后,我在Linux上使用Valgrind构建并运行它:
g++ test.cc && valgrind ./a.out
==8511== Memcheck, a memory error detector
...
==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== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

在这里,即使有1个分配和0个空闲,也没有内存泄漏。此question的答案引用了Valgrind的FAQ中的这一段作为解释-

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.



我的主要问题是:

C++库的实现是如何实现的?它是否在后台处理来自其标准模板的所有分配请求的单独进程,以便在程序退出时(此处为a.out),不会立即将内存分配给OS?如果是这样,它将何时退还?我如何检查该过程确实存在?如果没有,那么幕后的“魔力”是什么?

另一个问题:

分配了71 KB。为什么这个数字?

谢谢:)

最佳答案

How does the C++ library implementation achieve that?



没有。 valgrind信息已经过时,我不认为任何现代C++实现都能做到。

Does it keep around a separate process in the background that handles all allocation requests from its standard templates, so that when the program exits (a.out here), the memory is not immediately given back to the OS?



不,你误会了。 valgrind文档并不是在谈论保持内存的寿命超过流程。只是在谈论将内存池保留在进程中,以便由进程分配和再分配的内存被保存在一个池中,并在以后重用(由同一进程!),而不是立即调用free。但是,如今没有人针对std::allocator这样做,因为std::allocator必须是通用的并且在所有情况下均能表现良好,并且无论如何,良好的malloc实现应该可以满足这些需求。用户使用tcmalloc或jemalloc之类的替代方案覆盖默认系统malloc也是很容易的,因此,如果std::allocator仅转发到malloc,那么它将获得替换malloc的所有好处。

If so, when will it give back, and how can I check the process indeed exists? If not, what is the "magic" behind the scene?



进程退出时,进程中的所有内存将返回到OS。没有魔术。

但是无论如何,您看到的分配都与此无关。

There is 71 KB allocated. Why this number?



您所看到的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下运行时,不会释放该池,因为这样做是不必要的(无论如何,该进程退出时,操作系统将对其进行回收)。

关于c++ - 当程序退出时,C++库实现如何分配内存但不释放内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45537965/

相关文章:

c++ - 用于计算乘数和除数值的优化算法

c++ - 结构声明范围

C++:扩展数组的函数

linux - 结构 "struct page"存储在 linux 内核中的什么位置?

python - 使用 Gensim 对每个文档中的特征进行评分。也是一个 Python 内存问题

ubuntu-16.04 - libstdc++。so.6:找不到 `GLIBCXX_3.4.20'版本

header-files - iostream 和 bits/stdc++.h 有什么区别??我们什么时候需要使用它们?

c++ - Caffe::net reshape

linker - 使用 g++ 链接无法搜索 -lstdc++

C++ 类 : undefined reference to method