Ошибка сегментации: переполнение стека

Следующее встречается в linux 2.6.32-220.7.1.el6.x86_64 и g++ 4.4.6.

Следующий код:

#include <iostream>
#include <cstdlib>

int PROB_SIZE   = 10000000;
using namespace std;

int main(int argc, char *argv[])    {

    unsigned int numbers[PROB_SIZE];
    cout << "Generating " << PROB_SIZE << " random numbers... " << flush;

    return 0;
}

Произведите следующий SIGSEGV: (gdb) run Запуск программы: / home / cpd20202 / sorting / error

Program received signal SIGSEGV, Segmentation fault.
0x000000000040093b in main (argc=1, argv=0x7fffffffe4f8) at error.cpp:13
13      cout << "Generating " << PROB_SIZE << " random numbers... " << flush;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.47.el6_2.5.x86_64 libgcc-4.4.6-3.el6.x86_64 libstdc++-4.4.6-3.el6.x86_64
(gdb) where
#0  0x000000000040093b in main (argc=1, argv=0x7fffffffe4f8) at error.cpp:13

У меня действительно нет идей.


person RSFalcon7    schedule 14.05.2012    source источник


Ответы (5)


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

person Joe    schedule 14.05.2012
comment
У этой машины 48 ГБ памяти ... - person RSFalcon7; 14.05.2012
comment
@ RSFalcon7, это размер кучи. Стек намного меньше. Следовательно, вам нужно выделить память в куче, а не в стеке. - person chris; 14.05.2012
comment
@ RSFalcon7 объем памяти в системе не имеет ничего общего с размером стека, обычно это ~ 1 МБ. - person Seth Carnegie; 14.05.2012
comment
@ RSFalcon7, объем памяти не связан с размером стека. Процессы начинаются с (небольшого) фиксированного объема памяти для использования функциями и вызовами функций. Если вам нужно больше, вам нужно нажать на кучу, в которой есть потенциал всей вашей физической памяти. - person zneak; 14.05.2012
comment
Я понимаю, что у стека может быть ограниченный объем памяти, но он отлично работает с linux 2.6.18-128.1.14.el5 и g ++ 4.1.2 на гораздо менее мощной машине, уменьшила ли версия ядра или g ++ размер стека ? - person RSFalcon7; 14.05.2012
comment
Мне удалось заставить это работать, выполнив следующие действия: #include ‹iostream› #include ‹cstdlib› #define PROB_SIZE 10000000 статических беззнаковых целых чисел [PROB_SIZE]; используя пространство имен std; int main (int argc, char * argv []) {cout ‹---------------- Генерирование ‹******************************************************************************************************************************************************************************************************************* возврат 0; } - person RSFalcon7; 14.05.2012
comment
@ RSFalcon7, объявление его глобально означает, что он больше не размещается в стеке. Чтобы ответить на ваш предыдущий пост, размер стека зависит от машины. Вы можете увеличить его, если хотите. - person chris; 14.05.2012

Это потому, что ваш массив больше, чем размер стека. Следовательно, ваша программа дает сбой, когда пытается добавить что-то новое во время вызова функции.

Ошибка, которую вы получаете, концептуально аналогична переполнению стека, за исключением того, что она вызвана невероятно большой локальной переменной, а не вложением слишком большого количества вызовов функций.

Стек - это небольшая область памяти, используемая функциями для обслуживания и локальных переменных. Он никогда не бывает большим, максимум несколько мегабайт. Вот почему вам понадобится динамическое размещение, чтобы избавиться от проблемы. Большинство динамических распределений будут касаться кучи, которая часто ограничена только вашей физической памятью.

Вам нужно будет разместить массив в куче. Для этого у вас есть несколько вариантов, самым простым из которых, вероятно, является использование std::vector<int>. Они ведут себя примерно так же, как обычные массивы, и их хранилище управляется автоматически, так что это не должно быть проблемой.

#include <vector>
#include <iostream>

int PROB_SIZE   = 10000000;
using namespace std;

int main()
{
    vector<int> numbers(PROB_SIZE);
    cout << "Generating " << PROB_SIZE << " random numbers... " << flush;

    return 0;
}
person zneak    schedule 14.05.2012
comment
Самый простой и обычно самый эффективный *. - person chris; 14.05.2012

Вашему процессу не хватает места в стеке для выделения десяти миллионов целых чисел. Это 40 мегабайт (или 80, если у вас int 64-разрядная версия), и процессы обычно начинаются со стека размером около одного мегабайта.

У вас есть два основных варианта:

  • Выделите свой массив как глобальную переменную (переместив его объявление за пределы main).
  • Разместите свой массив в куче, используя malloc, new или std::vector.
person Greg Hewgill    schedule 14.05.2012
comment
Несмотря на то, что это решит непосредственную проблему, я бы посоветовал не переносить переменные в глобальную область видимости. - person zneak; 14.05.2012
comment
... или сохраняя локальную область видимости, давая ей статическую продолжительность хранения, определяя ее как static (хотя std::vector, вероятно, правильный выбор). - person Jerry Coffin; 14.05.2012

Это не cout. Вы размещаете в стеке очень большой массив numbers и взрываете свой стек. Стек обычно составляет 8 МБ или около того, а массив - около 40 МБ.

int v[size]; // stack
int v* = new int[size]; // heap
person Anycorn    schedule 14.05.2012
comment
@chris ulimit -s на моих машинах vanilla ubuntu (amd64) возвращает 8192. - person Anycorn; 14.05.2012
comment
Из того, что я видел у большинства людей, это 1 МБ, если они его не изменят. Это обязательно будет отличаться от человека к человеку, но я почти уверен, что 1 МБ является наиболее распространенным. - person chris; 14.05.2012
comment
@chris хм, я только что протестировал пять Linux-машин (все x64), самый низкий - 8 МБ, может быть 32/64 бит. - person Anycorn; 14.05.2012
comment
Я тестировал это на своей x64 Windows, и мне кажется, что это чуть больше 2 МБ. - person chris; 14.05.2012
comment
Я знаю разницу между ними;) Чего я не знал, так это того, что в моем стеке всего 1 МБ: $ ulimit -s 10240 - person RSFalcon7; 14.05.2012
comment
@ RSFalcon7 это 10 МБ. лимиты в 1024 блоках - person Anycorn; 14.05.2012

Вы выделяете слишком много места для обработки стека (10 миллионов целых чисел - очень большая сумма).

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

malloc (sizeof (int) * 10000000);

person RoneRackal    schedule 14.05.2012