gpt4 book ai didi

c++ - Linux 分配器不会释放小块内存

转载 作者:IT老高 更新时间:2023-10-28 22:25:28 25 4
gpt4 key购买 nike

Linux glibc 分配器的行为似乎很奇怪。希望有人可以对此有所了解。这是我拥有的源文件:

first.cpp:

#include <unistd.h>
#include <stdlib.h>
#include <list>
#include <vector>

int main() {

std::list<char*> ptrs;
for(size_t i = 0; i < 50000; ++i) {
ptrs.push_back( new char[1024] );
}
for(size_t i = 0; i < 50000; ++i) {
delete[] ptrs.back();
ptrs.pop_back();
}

ptrs.clear();

sleep(100);

return 0;
}

second.cpp:

#include <unistd.h>
#include <stdlib.h>
#include <list>

int main() {

char** ptrs = new char*[50000];
for(size_t i = 0; i < 50000; ++i) {
ptrs[i] = new char[1024];
}
for(size_t i = 0; i < 50000; ++i) {
delete[] ptrs[i];
}
delete[] ptrs;

sleep(100);

return 0;
}

我都编译了:

$ g++ -o first first.cpp$ g++ -o second second.cpp

I run first, and after it's sleeping, I see the resident memory size:

When I compile first.cpp, and run it, I look at memory with ps:

$ ./first&
$ ps aux | grep first
davidw 9393 1.3 0.3 64344 53016 pts/4 S 23:37 0:00 ./first


$ ./second&
$ ps aux | grep second
davidw 9404 1.0 0.0 12068 1024 pts/4 S 23:38 0:00 ./second

注意常驻内存大小。首先,常驻内存大小为 53016k。其次是1024k。首先从未出于某种原因将分配释放回内核。

为什么第一个程序不将内存释放给内核,而第二个程序却可以?我知道第一个程序使用链表,链表可能会在同一页面上分配一些节点作为我们正在释放的数据。但是,这些节点应该被释放,因为我们要弹出这些节点,然后清除链表。如果你通过 valgrind 运行这些程序中的任何一个,它就不会出现内存泄漏。可能发生的情况是内存在 first.cpp 中变得碎片化,而在 second.cpp 中没有。但是,如果一个页面上的所有内存都被释放,那么该页面如何不被释放回内核呢?将内存交还给内核需要什么?如何修改 first.cpp(继续将 char* 放入列表中)以便将内存让给内核。

最佳答案

这种行为是有意的,glibc 使用一个可调阈值来决定是否将内存实际返回给系统,或者是否缓存它以供以后重用。在您的第一个程序中,您使用每个 push_back 进行大量小分配,这些小分配不是连续的 block ,并且可能低于阈值,因此不要返回给操作系统。

调用malloc_trim(0)清除列表后应该会导致 glibc 立即将空闲内存的最顶层区域返回给系统(下次内存时需要 sbrk 系统调用需要。)

如果您确实需要覆盖默认行为(除非分析表明它确实有帮助,否则我不建议您这样做),那么您可能应该使用 strace 和/或尝试 mallinfo至看看你的程序实际发生了什么,也许使用 mallopt至调整内存返回系统的阈值。

关于c++ - Linux 分配器不会释放小块内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10943907/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com