Получение исключения переполнения стека при объявлении большого массива - PullRequest
35 голосов
/ 21 февраля 2009

Следующий код генерирует для меня ошибку переполнения стека

int main(int argc, char* argv[])
{
    int sieve[2000000];
    return 0;
}

Как мне обойти это? Я использую Turbo C ++, но хотел бы сохранить мой код в C

EDIT:

Спасибо за совет. Код выше был только для примера, я фактически объявляю массив в функции, а не в подоснове. Кроме того, мне нужно было инициализировать массив в нули, поэтому, когда я гуглил malloc, я обнаружил, что calloc идеально подходит для моих целей.

Malloc / calloc также имеет преимущество перед размещением в стеке, позволяя мне объявлять размер с помощью переменной.

Ответы [ 9 ]

52 голосов
/ 21 февраля 2009

Ваш массив слишком большой, чтобы поместиться в стек, рассмотрите возможность использования кучи:

int *sieve = malloc(2000000 * sizeof(*sieve));

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

Совет : - Не забудьте освободить динамически выделенную память, когда она больше не нужна.

12 голосов
/ 21 февраля 2009

Есть 3 способа:

  1. Выделить массив в куче - используйте malloc(), как предлагали другие авторы. Не забудьте free() это (хотя для main() это не так важно - ОС очистит память для вас после завершения программы).
  2. Объявление массива на уровне блока - он будет размещен в сегменте данных и будет виден всем (добавление static к объявлению ограничит видимость для блока).
  3. Объявите ваш массив как static - в этом случае он будет размещен в сегменте данных, но виден только в main().
2 голосов
/ 21 февраля 2009

Вы бы лучше разместили его в куче, а не в стеке. что-то вроде

int main(int argc, char* argv[])
{
    int * sieve;
    sieve = malloc(20000);
    return 0;
}
1 голос
/ 22 февраля 2009

Используйте malloc. Все проверяют, что возвращаемый тип не равен нулю, если он равен нулю, ваша система просто не имеет достаточно памяти, чтобы вместить столько значений.

1 голос
/ 21 февраля 2009

Это около 7 МБ стекового пространства. В Visual Studio вы должны использовать / STACK: ###, ###, чтобы отразить желаемый размер. Если вы действительно хотите огромный стек (это может быть хорошая причина, используя LISP или что-то :), даже если куча ограничена небольшими выделениями, прежде чем вы заставите использовать VirtualAlloc), вы также можете настроить свой PE для сборки с / LARGEADDRESSAAWARE (снова компоновщик Visual Studio), но эта конфигурация является вашим PE-заголовком, чтобы позволить вашему скомпилированному двоичному файлу адресовать все 4 ГБ 32-битного адресного пространства (если выполняется в WOW64). Если вы создаете действительно массивные двоичные файлы, вам, как правило, также необходимо настроить / bigobj как дополнительный параметр компоновщика.

И если вам все еще нужно больше места, вы можете радикально нарушить соглашение, используя что-то симуляционное для (опять-таки ссылка MSVC) / merge:, что позволит вам упаковать один раздел в другой, чтобы вы могли использовать каждый отдельный байт для единый общий код / ​​раздел данных. Естественно, вам также необходимо настроить разрешения SECTIONS в файле def или с помощью # pgrama.

0 голосов
/ 13 июля 2017

Поскольку Turbo C / C ++ является 16-битным компилятором, тип данных int потребляет около 2 байтов. 2 байта * 2000000 = 40,00 000 байтов = 3,8147 МБ.

Автоматические переменные функции сохраняются в стеке, что вызывает переполнение стековой памяти. Вместо этого используйте память данных [используя статическую или глобальную переменную] или динамическую память кучи [используя malloc / calloc] для создания необходимой памяти в соответствии с доступностью отображения памяти процессора.

0 голосов
/ 04 июля 2016

Ваш массив огромен.

Возможно, ваша машина или ОС не имеют или не хотят выделять столько памяти.


Если вам абсолютно необходим огромный массив, вы можете попытаться выделить его динамически (используя malloc(...)), но тогда вы рискуете потерять память. Не забудьте освободить память.

Преимущество malloc в том, что он пытается выделить память в куче, а не в стеке (поэтому вы не получите переполнение стека).

Вы можете проверить значение, которое возвращает malloc, чтобы увидеть, было ли выделение успешным или неудачным. Если это не удается, просто попробуйте распределить массив меньшего размера.


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

Еще один вариант - хранить вещи в файле, передавая данные на лету. Этот подход самый медленный.

Если вы собираетесь хранить данные на жестком диске, вы также можете использовать существующую библиотеку (для баз данных)

0 голосов
/ 12 мая 2014

Используйте malloc вместо. Синтаксис:

newnode=(struct node *)malloc(sizeof(struct node))
0 голосов
/ 21 февраля 2009

Есть ли какая-то причина, по которой вы не можете использовать alloca () для выделения необходимого пространства в кадре стека в зависимости от того, насколько большим должен быть объект в действительности?

Если вы сделаете это, и все еще разрушаете стек, поместите его в выделенную кучу. Я настоятельно рекомендую НЕ объявлять его как статическое в main () и помещать его в сегмент данных.

Если оно действительно должно быть таким большим, и ваша программа не может разместить его в куче, ваша программа действительно не должна работать на этом типе компьютеров с самого начала.

Что (именно) вы пытаетесь достичь?

...