C / C ++ максимальний розмір стека програми


115

Я хочу зробити DFS на масиві 100 X 100. (Скажімо, елементи масиву представляють вузли графіків) Отже, припускаючи, що в гіршому випадку глибина рекурсивних викликів функцій може підніматися до 10000, кожен виклик займає до 20 байт. Тож чи є можливим засобом, чи існує можливість стакаверху?

Який максимальний розмір стека в C / C ++?

Вкажіть, будь ласка, gcc для обох
1) cygwin у Windows
2) Unix

Які загальні межі?


11
Ви знаєте, що ви можете здійснити пошук на глибині перших без рекурсії, правда?
Себастьян

4
Ні, я не знаю, поясніть, будь ласка.
avd

1
Я зробив невеликий приклад DFS без рекурсії у своїй відповіді
Андреас Брінк

56
плюс один за запитання про фактичне переповнення стека
Сем Уоткінс

3
@SamWatkins Так, одна з найбільших проблем для мене з назвою Stack Overflow полягає в тому, що я можу шукати "переповнення стека" в Google і знаходитись на цьому веб-сайті, але не обов'язково / менш вірогідно в питаннях про переповнення стека ...
lalilulelost

Відповіді:


106

У Visual Studio розмір стека за замовчуванням становить 1 Мб, я думаю, тому при глибині рекурсії в 10000 кожен кадр стека може бути не більше ~ 100 байт, що повинно бути достатньо для алгоритму DFS.

Більшість компіляторів, включаючи Visual Studio, дозволяють вказати розмір стека. У деяких (все?) Linux смаках розмір стека не є частиною виконуваного файлу, але змінною середовища в ОС. Потім ви можете перевірити розмір стека за допомогою ulimit -sі, наприклад, встановити його на нове значення ulimit -s 16384.

Ось посилання з типовими розмірами стека для gcc.

DFS без рекурсії:

std::stack<Node> dfs;
dfs.push(start);
do {
    Node top = dfs.top();
    if (top is what we are looking for) {
       break;
    }
    dfs.pop();
    for (outgoing nodes from top) {
        dfs.push(outgoing node);
    }
} while (!dfs.empty())

12
І лише для довідки, BFS - це те саме, що ви використовуєте FIFO замість стека.
Стів Джессоп

Так, або в STL-lingo використовуйте std :: deque з pop_front / push_back
Andreas

ваш DFS з результатами стеку буде відрізнятися від рекурсійної версії. У деяких випадках це не має значення, але в інших (наприклад, у топологічному роді) ви отримаєте неправильні результати
spin_eight

Так, обмеження за замовчуванням для VS дійсно становить 1 МБ. Більше інформації та спосіб встановити інше значення можна знайти у документації Microsoft: msdn.microsoft.com/en-us/library/tdkhxaks(v=vs.140).aspx
FrankS101

Я вважаю за краще використовувати явну структуру даних стека для таких алгоритмів, а не рекурсію, так що 1. не залежить від розміру системного стеку; 2. можу змінити алгоритм для використання іншої структури даних, наприклад, черги або черги пріоритету без викидання з усіх кодів.
Сем Уоткінс

47

штабелі для ниток часто менші. Ви можете змінити типовий час підключення або також змінити час виконання. Для довідки деякі за замовчуванням є:

  • glibc i386, x86_64 7,4 Мб
  • Tru64 5.1 5.2 Мб
  • Cygwin 1,8 Мб
  • Solaris 7..10 1 Мб
  • MacOS X 10,5 460 Кб
  • AIX 5 98 Кб
  • OpenBSD 4.0 64 Кб
  • HP-UX 11 16 Кб


17

Платформа-залежна від інструментальної мережі, залежна від обмежених параметрів, залежна від параметрів .... Це зовсім не визначено, і існує багато статичних і динамічних властивостей, які можуть впливати на це.


4
"Загальних обмежень" немає. У Windows із типовими параметрами зв’язків VC ++ та поведінкою CreateThread за замовчуванням, як правило, близько 1 МіБ на потік. В Linux, з необмеженим користувачем, я вважаю, що обмежень зазвичай немає (стек може просто зростати вниз, займаючи майже весь адресний простір). В основному, якщо вам доведеться запитати, ви не повинні використовувати стек.
DrPizza

1
У вбудованих системах у вас може бути 4k або менше. У такому випадку вам доведеться запитати, навіть коли розумно використовувати стек. Відповідь - це звичайно галльська плечима.
Стів Джессоп

1
Ну правда, також часто буває в режимі ядра.
DrPizza

6

Так, є можливість переповнення стека. Стандарт C і C ++ не диктує такі речі, як глибина стека, це, як правило, екологічна проблема.

Більшість гідних середовищ розробки та / або операційних систем дозволять вам підібрати розмір стека процесу, як за посиланням, так і за часом завантаження.

Ви повинні вказати, яку ОС та середовище розробки ви використовуєте для отримання більш цільової допомоги.

Наприклад, у Ubuntu Karmic Koala за замовчуванням для gcc є 2M зарезервовано і 4K дозволено, але це можна змінити, коли ви пов'язуєте програму. Скористайтеся --stackопцією " ldзробити це".


2
@lex: загальних обмежень немає. Це залежить від безлічі параметрів.
Майкл Фукаракіс

@paxdiablo: ЩО означає сенс зарезервованого та скоєного?
avd

2
Зарезервовано - скільки адресного простору виділити, скоєне - скільки прикріпити резервне сховище. Іншими словами, резервування адресного простору не означає, що пам’ять буде там, коли вам це потрібно. Якщо ви ніколи не використовуєте стек більше 4К, ви не витрачаєте реальну пам’ять на інші 1.6M. Якщо ви хочете гарантувати, буде достатньо стека, зарезервоване і введене має бути однаковим.
paxdiablo

2
@paxdiablo 2M - 4k не 1.6M. Просто кажу. (мене бентежить перші 3 рази, коли я прочитав ваш коментар)
griffin

2
@griffin, kudos для першої особи, яка спіймала це за 3+ років. Я, звичайно , мав в виду «інше» - я уникнете фактичну цифру , щоб не зробити ще одну можливу помилку :-)
paxdiablo

5

У мене просто не вистачало стека в роботі, це була база даних, і вона працювала з деякими потоками, в основному попередній розробник кинув великий масив на стек, а стек все одно був низьким. Програмне забезпечення було складено за допомогою Microsoft Visual Studio 2015.

Незважаючи на те, що в потоці закінчився стек, він мовчки провалився і продовжував роботу, стек переповнювався лише тоді, коли з'явився доступ до вмісту даних в стеку.

Найкраща порада, яку я можу дати, - це не оголошувати масиви на стеку - особливо у складних програмах і особливо в потоках, а не купувати. Ось для чого це;)

Також пам’ятайте, що він може не вийти з ладу відразу при оголошенні стека, а лише під час доступу. Я здогадуюсь, що компілятор оголошує стек під Windows "оптимістично", тобто буде вважати, що стек був оголошений і має достатній розмір, поки не прийде його використовувати, а потім з’ясує, що стека немає.

У різних операційних системах можуть бути різні політики декларування стека. Залиште коментар, якщо ви знаєте, що таке політика.


3

Я не впевнений, що ви маєте на увазі під час глибокого пошуку на прямокутному масиві, але я припускаю, що ви знаєте, що робите.

Якщо ліміт стеку є проблемою, ви повинні мати можливість перетворити своє рекурсивне рішення в ітераційне рішення, яке висуває проміжні значення на стек, який виділяється з купи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.