考虑下面这段创建了100,000个大小为4KB的页面的C代码,然后释放99,999个页面,并最终释放最后一个页面:
#include <stdio.h>
#include <stdlib.h>
#define NUM_PAGES 100000
int main() {
void *pages[NUM_PAGES];
int i;
for(i=0; i<NUM_PAGES; i++) {
pages[i] = malloc(4096);
}
printf("%d pages allocated.\n", NUM_PAGES);
getchar();
for(i=0; i<NUM_PAGES-1; i++) {
free(pages[i]);
}
printf("%d pages freed.\n", NUM_PAGES-1);
getchar();
free(pages[NUM_PAGES-1]);
printf("Last page freed.\n");
getchar();
return 0;
}
如果你编译并运行它,同时监控进程的内存使用情况,你会发现在第一个
getchar
之前(当内存被分配给100,000个页面时),内存使用量达到了约400MB,然后即使在99,999个页面被释放之后(第二个getchar
之后),内存使用量仍然保持不变,最后当最后一页被释放时,内存使用量降至1MB。那么,我的问题是为什么会出现这种情况?为什么只有当所有页面都被释放时才将整个内存返回给操作系统?是否有任何页面大小或页面对齐方式可以防止这种情况发生?我的意思是,是否有任何页面大小或对齐方式可以使任何已分配的页面在只释放一个页面时就完全返回给操作系统?
sbrk()
来动态调整其未初始化的数据。由于它是顺序的,因此只能在释放最新的分配时缩小。如果将分配大小增加到131072字节(128k),则strace
显示它会改用mmap()
进行分配,并且每个free()
实际上会将分配返回给操作系统。因此,请使用分配缓存,并仅向操作系统请求/返回较大的块。 - Nominal Animal