Будет ли когда-нибудь уменьшаться стек C-программы? - PullRequest
4 голосов
/ 20 ноября 2011

Я заметил, что у каждой работающей программы на С есть частное отображение, называемое [стек], которое изначально довольно мало (128 КБ на моей машине), но будет расти для размещения любых автоматических переменных (до предела размера стека). Я предполагаю, что именно здесь находится стек вызовов моей программы.

Однако, похоже, он никогда не уменьшится до своего первоначального размера. Есть ли способ освободить эту память, не прерывая процесс?

Как внутренне реализован стек C; что увеличивает размер отображения [стека] по требованию? Какой-то код, сгенерированный компилятором, библиотека C или операционная система? Где происходит увеличение?

Обновление : я использую Linux 3.0.0, gcc 4.6.1 и glibc6 на x86-64; поскольку это, вероятно, довольно специфично для реализации, любая информация о том, как это работает, будет в порядке.

Ответы [ 3 ]

6 голосов
/ 20 ноября 2011

Это зависит от конкретной реализации, но я не знаю ни одной широко используемой платформы, которая бы уменьшала выделенную память стека.Стеки, как правило, растут по требованию, но как только место занято, оно остается выделенным.

3 голосов
/ 20 ноября 2011

Я считаю, что ядро ​​Linux наращивает сегмент стека (только для основного потока). Он не находится в компиляторе (за исключением увеличения указателя стека на вызовы и игнорирования экспериментальной опции -fsplit-stack недавнего GCC), и не в libC.

Если вы уверены, что ваш стек стал слишком большим, и он вам не понадобится, вы, возможно, munmap можете неиспользованную часть (но будьте осторожны; разработчики ядра не думают об этом, поэтому он может не работать как ожидается, в начале 1990-х я вспомнил, как разбил SunOS5.0 на Sparc с такими грязными уловками).

А на Linux, x86-64, с приличной машиной вам действительно наплевать. Стек не такой большой ...

Я предполагаю, что сегмент стека mmap -едан с MAP_NORESERVE MAP_STACK MAP_GROWSDOWN, но я могу ошибаться.

1 голос
/ 22 ноября 2011

В 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 увеличить стек, есть ли слишком много овермитов и т. Д., И, наконец, увеличивает стек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...