gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 03:43:49 25 4
gpt4 key购买 nike

Linux glibc 分配器似乎表现得很奇怪。希望有人能对此有所启发。这是我的源文件:

第一个.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;
}

第二个.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 中的内存出现碎片,而 secondary.cpp 中却没有。但是,如果释放页面上的所有内存,该页面如何不被释放回内核?内存被释放回内核需要什么?如何修改first.cpp(继续将char*放入列表中)以便将内存让给内核。

最佳答案

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

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

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

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

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