Есть ли ограничение на стековую память?

Я просматривал одну из тем. Произошел сбой программы, потому что она объявила массив 10^6 локально внутри функции.

Указанная причина заключалась в том, что сбой выделения памяти в стеке приводит к сбою.

когда тот же массив был объявлен глобально, он работал хорошо (память в куче сохраняла его).

Теперь на данный момент, допустим, стек растет вниз, а куча вверх.

У нас есть:

---КУЧА---

-------------------

--- КУЧА ----

Теперь я считаю, что если есть сбой в выделении в стеке, он должен также дать сбой в куче.

Итак, мой вопрос: есть ли ограничение на размер стека? (превышение предела привело к сбою программы). Или я что-то упускаю?


person Vikas    schedule 06.05.2010    source источник
comment
Здесь замешан небольшой миф. Вы можете проверить этот ответ.   -  person RBT    schedule 06.02.2017


Ответы (6)


Все зависит от того, какой язык и компилятор вы используете. Но программы, скомпилированные, например, с помощью C или C++, выделяют стек фиксированного размера при запуске программы. Размер стека обычно можно указать во время компиляции (в моем конкретном компиляторе по умолчанию он равен 1 МБ).

person Andreas Brinck    schedule 06.05.2010
comment
Я использую С/С++. Компилятор — gcc.Windows Platform. Также я не получаю ошибок во время выполнения, делая то же самое на платформе Linux. Я могу с комфортом объявить массив размером 10^6 локально. Так что насчет платформы? - person Vikas; 06.05.2010
comment
Я хочу создать массив 2d с плавающей запятой размером [400] [3000].... используя gcc в Linux, но из-за нехватки памяти не могу! любое предложение ???? - person dom; 25.10.2015

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

Обычно значения по умолчанию (если не установлены вручную) составляют около 1 МБ для текущих языков, чего достаточно, если вы не делаете что-то, что обычно не рекомендуется (например, вы выделяете огромные массивы в стеке).

person Foxfire    schedule 06.05.2010

Вопреки всем ответам до сих пор, в Linux с GCC (и я думаю, что это верно для всех современных операционных систем POSIX) максимальный размер стека - это предел безопасности, установленный операционной системой, который можно легко снять.

Я создал небольшую программу, которая рекурсивно вызывает функцию до тех пор, пока в стеке не будет выделено не менее 10 ГБ, ждет ввода на терминале, а затем безопасно возвращается из всех рекурсивных вызовов до main.

#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>

void grow(unsigned cur_size)
{
    if(cur_size * sizeof(int) < 10ul*1024ul*1024ul*1024ul) {
        unsigned v[1000];
        v[0] = cur_size;
        for(unsigned i = 1; i < 1000; ++i) {
            v[i] = v[i-1] + 1;
        }

        grow(cur_size + 1000);

        for(unsigned i = 0; i < 1000; ++i) {
            if(v[i] != cur_size + i)
                puts("Error!");
        }
    } else {
        putchar('#');
        getchar();
    }
}

int main()
{
    struct rlimit l;
    l.rlim_max = RLIM_INFINITY;
    l.rlim_cur = RLIM_INFINITY;
    setrlimit(RLIMIT_STACK, &l);

    grow(0);
    putchar('#');
    getchar();
}
person lvella    schedule 15.03.2016

Вы не указываете, какой язык программирования, но в Delphi параметры компиляции включают максимальный и минимальный размер стека, и я полагаю, что аналогичные параметры будут существовать для всех компилируемых языков.

Мне, конечно, приходилось время от времени увеличивать максимум.

person Cruachan    schedule 06.05.2010
comment
Это С/С++. Компилятор-GCC. Платформа: Windows. Также, пожалуйста, прочитайте мои комментарии ниже. - person Vikas; 06.05.2010
comment
@Vikas: Старайтесь не ссылаться на «ниже». Порядок сообщений на SO не является статичным. - person Xavier Ho; 07.05.2010
comment
@Xavier: О, понятно. Спасибо за информацию. :) - person Vikas; 09.05.2010

Да, в большинстве языков существует ограничение на размер стека. Например, в C/C++, если у вас неправильно написана рекурсивная функция (например, неправильный базовый регистр), вы переполнитесь стеком. Это связано с тем, что при игнорировании хвостовой рекурсии каждый вызов функции создает новый фрейм стека, который занимает место в стеке. Сделайте это достаточно, и вам не хватит места.

Запуск этой программы C в Windows (VS2008)...

void main()
{
    main();
}

... приводит к переполнению стека:

Unhandled exception at 0x004113a9 in Stack.exe: 0xC00000FD: Stack overflow.

person Chris Schmich    schedule 06.05.2010
comment
да, конечно, это даст ошибку времени выполнения. Но я сомневался: если объявление массива локально (в стеке) вызвало ошибку времени выполнения. Почему он убежал глобально. означает, что у нас есть предел размера кучи, превышающий размер стека. Может быть по умолчанию!! - person Vikas; 06.05.2010
comment
Первая ошибка, которую я получаю, это Тип возвращаемого значения не int, поэтому лучше сначала избавиться от нестандартного кода. - person HaseeB Mir; 27.11.2018

Возможно, это не очень хороший ответ, но он дает вам более подробное представление о том, как Windows в целом управляет памятью: Раздвигая границы Windows

person Oliver    schedule 06.05.2010