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但我可能是错误的。

链接地址: http://www.djcxy.com/p/80279.html

上一篇: Will the stack of a C program ever shrink?

下一篇: What is the maximum size of stack segment that can be allocated to a process?