C程序的堆栈会缩小吗?
我注意到每个正在运行的C程序都有一个名为[stack]的私有映射,它最初非常小(我的机器上为128k),但会增长以适应任何自动变量(达到堆栈大小限制)。 我认为这是我的程序调用堆栈所在的位置。
但是,它似乎并没有缩回到原来的大小。 有没有办法在不终止流程的情况下释放内存?
C栈如何在内部实现; 根据需求增加[堆栈]映射的大小? 一些编译器生成的代码,C库或操作系统? 增加在哪里触发?
更新:我在x86-64上使用Linux 3.0.0,gcc 4.6.1和glibc6; 因为这可能是相当具体的实现,所以关于它如何工作的任何信息都可以。
在Linux / MMU中(MMU中你不能增长堆栈),堆栈增长在页面错误处理程序中。 对于x86,是否增长堆栈arch/x86/mm/fault.c:do_page_fault()
的以下代码arch/x86/mm/fault.c:do_page_fault()
:
if (error_code & PF_USER) {
/*
* Accessing the stack below %sp is always a bug.
* The large cushion allows instructions like enter
* and pusha to work. ("enter $65535, $31" pushes
* 32 pointers and then decrements %sp by 65535.)
*/
if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
bad_area(regs, error_code, address);
return;
}
}
if (unlikely(expand_stack(vma, address))) {
bad_area(regs, error_code, address);
return;
}
expand_stack()
检查通常的RLIMITS(RLIMIT_AS,RLIMIT_STACK,RLIMIT_MEMLOCK),LSM是否允许堆栈增长,是否有太多的overcommit等等,并最终增长堆栈。
它是特定于实现的,但我知道没有缩小提交堆栈内存的常用平台。 堆栈的需求随着需求的增长而增加,但一旦空间承诺,它将继续承诺。
我相信Linux内核正在增加堆栈段(仅针对主线程)。 它不在编译器中(除了在调用时递增堆栈指针,并忽略最近GCC的实验性-fsplit-stack
选项),而不是在libC中。
如果你确定自己的堆栈已经变得太大了,而且你不需要它,那么你可能需要munmap
未使用的部分(但要小心;内核开发人员不会这样想,所以它可能无法按预期工作;在早期1990-s我记得在Sparc上使用这种肮脏的技巧撞击了SunOS5.0)。
而在Linux上,x86-64,一台体面的机器,你真的不应该在意。 堆栈不是那么大...
我的猜测是堆栈段使用MAP_NORESERVE
MAP_STACK
MAP_GROWSDOWN
进行了mmap
MAP_GROWSDOWN
但我可能是错误的。
上一篇: Will the stack of a C program ever shrink?
下一篇: What is the maximum size of stack segment that can be allocated to a process?