Получение исключения переполнения стека при объявлении большого массива
следующий код вызывает ошибку переполнения стека для меня
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 способа:
- выделить массив в куче-использовать
malloc()
, как и другие плакаты предложили. Не забудьтеfree()
(хотя дляmain()
это не так важно-OS очистит память для вас при завершении программы). - объявить массив на уровне единицы-он будет выделен в сегменте данных и виден для всех (добавление
static
объявление ограничит видимость до единицы). - объявить массив как
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, чтобы позволить вашему скомпилированному двоичному файлу обращаться к полному 4GB 32'bit адресное пространство (если работает в WOW64). Если дом действительно массовым двоичные файлы, вы также, как правило, нужно настроить /bigobj в качестве дополнительного paramerter линкер.
и если вам все еще нужно больше места, вы можете радикально нарушить соглашение, используя что-то аналогичное (снова ссылка MSVC) /merge:, что позволит вам упаковать один раздел в другой, поэтому вы можете использовать каждый байт для одного общего раздела кода/данных. Естественно, вам также нужно будет настроить разделы разрешения в файле def или с #pgrama.
использовать malloc. Все проверяют, что тип возврата не равен null, если он равен null, то ваша система просто не имеет достаточно памяти, чтобы соответствовать этому количеству значений.
есть ли какая-то причина, по которой вы не можете использовать alloca() для выделения необходимого вам пространства в кадре стека на основе того, насколько большим должен быть объект?
Если вы это сделаете, и все равно сломаете стек, поместите его в выделенную кучу. Я настоятельно рекомендую не объявлять его статическим в main () и помещать его в сегмент данных.
Если это действительно должен быть таким большим, и ваша программа не может выделить его в куче, ваша программа действительно не работает на этом тип машины для начала.
Что (именно) вы пытаетесь достичь?
массив огромный.
возможно, что ваша машина или ОС не имеют или не хотят выделять столько памяти.
Если вам абсолютно нужен огромный массив, вы можете попытаться выделить его динамически (используя malloc(...)
), но тогда вы рискуете утечки памяти. Не забудьте освободить память.
преимущество Танос является то, что он пытается выделить память в куче, вместо стека (поэтому вы не получите стек переполнение.)
вы можете проверить значение, которое возвращает malloc, чтобы увидеть, было ли распределение успешным или неудачным. Если это не удается, просто попробуйте malloc меньший массив.
другой вариант-использовать другую структуру данных, которая может быть изменена на лету (например, связанный список). Будет ли эта опция хороша, зависит от того, что вы собираетесь делать с данными.
еще одним вариантом было бы хранить вещи в файле, потоковые данные на лету. Такой подход самый медленный.
Если вы идете для хранения на жестком диске, вы могли бы также использовать существующую библиотеку (для баз данных)
поскольку Turbo C / C++ - 16-битный компилятор int datatype потребляет около 2 байт. 2 байта*2000000=40,00,000 байт=3.8147 МБ пространства.
автоматические переменные функции хранятся в стеке, и это вызвало переполнение памяти стека. Вместо этого используйте память данных [используя статическую или глобальную переменную] или динамическую память кучи [используя malloc/ calloc] для создания требуемой памяти в соответствии с доступностью сопоставления памяти процессора.