Получение исключения переполнения стека при объявлении большого массива

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

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

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

РЕДАКТИРОВАТЬ:

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

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

9 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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


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

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

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

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

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

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

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

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

newnode=(struct node *)malloc(sizeof(struct node))
Другие вопросы по тегам