use*_*199 15 c++ memory heap allocation
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;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
我编译了两个:
$ g++ -o first first.cpp $ g++ -o second second.cpp
我先运行,在它休眠后,我看到常驻内存大小:
当我编译first.cpp并运行它时,我用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
Run Code Online (Sandbox Code Playgroud)
注意常驻内存大小.首先,驻留内存大小为53016k.第二,它是1024k.First从未出于某种原因将分配释放回内核.
为什么第一个程序不会将内存放弃到内核,但第二个程序呢?据我所知,第一个程序使用链表,链表可能会在我们释放的数据中分配同一页面上的一些节点.但是,应该释放这些节点,因为我们将关闭这些节点,然后清除链接列表.如果你通过valgrind运行这些程序中的任何一个,它会返回没有内存泄漏.可能发生的是在first.cpp中的内存碎片,而不是在second.cpp中.但是,如果页面上的所有内存都被释放,那么该页面如何不被放弃回内核?将内存放回内核需要什么?如何修改first.cpp(继续将char*放在列表中),以便将内存放到内核中.
Jon*_*ely 17
这种行为是故意的,glibc使用一个可调阈值来决定是否实际将内存返回给系统,或者是否将其缓存以供以后重用.在你的第一个程序中,你为每个程序做了很多小的分配,push_back
那些小的分配不是一个连续的块,大概低于阈值,所以不要返回到操作系统.
malloc_trim(0)
清除列表后调用应该使glibc立即将最上面的可用内存区域返回给系统(sbrk
下次需要内存时需要系统调用.)
如果你真的需要覆盖默认行为(我不建议除非分析显示它实际上有帮助)那么你应该使用strace和/或试验
mallinfo
来查看你的程序中实际发生了什么,并可能使用mallopt
调整阈值用于将内存返回给系统.
通常,分配的内存new
只会在进程终止时返回给系统。在第二种情况下,我怀疑是libc
对非常大的连续块使用特殊的分配器,它确实返回了它,但如果您的任何一个new char[1024]
被返回,我会感到非常惊讶,并且在许多 Unices 上,即使是大块也不会返回被退回。
归档时间: |
|
查看次数: |
3549 次 |
最近记录: |