C程序的堆栈是否会缩小?

时间:2011-11-20 17:03:59

标签: c stack

我注意到每个正在运行的C程序都有一个名为[stack]的私有映射,它最初非常小(在我的机器上为128k),但会增长以适应任何自动变量(最大为堆栈大小限制)。我假设这是我的程序的调用堆栈所在的位置。

然而,它似乎并没有缩小到原来的大小。有没有办法在不终止进程的情况下释放内存?

如何在内部实现C堆栈;是什么增加了[堆栈]按需映射的大小?有些编译器生成代码,C库或操作系统?增加的触发点在哪里?

更新:我在x86-64上使用Linux 3.0.0,gcc 4.6.1和glibc6;因为这可能是非常具体的实现,任何有关它如何工作的信息都可以。

3 个答案:

答案 0 :(得分:6)

这是特定于实现的,但我知道没有常用的平台可以缩小已提交的堆栈内存。堆栈按需增长是很常见的,但是一旦提交空间就会保持承诺。

答案 1 :(得分:3)

我相信Linux内核正在增长堆栈段(仅适用于主线程)。它不在编译器中(除了通过在调用时递增堆栈指针,忽略最近GCC的实验-fsplit-stack选项),而不是在libC中。

如果您确定您的堆栈已经变得太大而且您不需要它,那么您可能会munmap未使用的部分(但要小心;内核开发人员不会这么想,所以它可能不会按照预期工作;在1990年代早期,我记得曾在Sparc上使用这些肮脏的技巧破坏了SunOS5.0。

在Linux,x86-64上,有一台不错的机器,你真的不应该在乎。堆栈不是那么大......

我猜是堆栈段是mmap - 用MAP_NORESERVE MAP_STACK MAP_GROWSDOWN编辑,但我可能错了。

答案 2 :(得分:1)

在Linux / MMU中(在!MMU中你无法增加堆栈),堆栈会在页面错误处理程序中生成。对于x86,是否增加堆栈由以下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是否允许增加堆栈,是否有过多的过度使用等等,最后增加堆栈。