2009-02-21 2 views
28

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

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

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

EDIT:

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

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

+1

все еще посмеиваясь @ «сито» – el2iot2

+6

Я прочитал «исключение переполнения стека» и подумал: «... что-то не так с сайтом?» Ясно, что я трачу слишком много времени здесь: -/ –

+1

Я уверен, что этот тип вопроса должен был появиться ранее на этом сайте, но поиск «переполнения стека» бесполезен –

ответ

46

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

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

Если вы действительно хотите изменить размер стека, take a look at this document.

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

+16

Поскольку это C, вам не нужно (и на самом деле не должно) отличать возвращаемое значение malloc. – aib

+1

Почему бы вам не отдать результат malloc? Разве вам не пришлось бы бросать его из пустоты *, чтобы сделать что-нибудь с ним? – Amy

+4

@ yodaj007: Вам не нужно явно указывать его. Поскольку назначенная переменная также относится к типу указателя, присваивание выполняет неявное преобразование. – jweyrich

2

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

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

вы забыли освободить (сито) –

+1

И проверить сито для NULL – paulm

+0

« Я только решу для вас »- -Zohan – DragonLord

1

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

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

11

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

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

Я бы просто сделал его статическим: 'main()' следует вызывать только один раз, поэтому нет ошибок; не нужно для 'malloc()' здесь ... – Christoph

0

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

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

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

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

+0

Я использую проблемы от ProjectEuler.net, чтобы узнать C, и реализую алгоритм Sieve of Eratosthenes, поэтому он должен быть таким большим. malloc отлично работает для моих целей, но –

1

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

-1

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

newnode=(struct node *)malloc(sizeof(struct node)) 
0

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

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


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

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

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


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

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

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

0

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

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

-3

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

+0

Добро пожаловать в Stack Overflow! У этого сообщения уже есть принятый ответ, а также ответы, очень похожие на ваши. В будущем, пожалуйста, уделите время, чтобы ваш ответ добавил ценность, отличную от тех, которые уже были предоставлены. См. [Как ответить] (https://stackoverflow.com/help/how-to-answer). – avojak

Смежные вопросы