На практиці виростити стек важко (а іноді і неможливо). Щоб зрозуміти, чому потрібно певне розуміння віртуальної пам'яті.
У Єдніх днях однопотокових програм та суміжної пам'яті три були три компоненти адресного простору процесу: код, купа та стек. Те, як ці три були розкладені, залежало від ОС, але, як правило, перший прийшов код, починаючи з нижньої частини пам’яті, купа йшла поруч і зростала вгору, а стек починався у верхній частині пам’яті і зростав вниз. Була також якась пам'ять, зарезервована для операційної системи, але ми можемо це ігнорувати. Програми в ті часи мали дещо драматичніші переповнення стека: стек врізався в купу, і залежно від того, який оновлювався спочатку, ви або працювали б з поганими даними, або поверталися з підпрограми в якусь довільну частину пам'яті.
Управління пам’яттю дещо змінило цю модель: з точки зору програми у вас все ще були три компоненти карти процесної пам’яті, і вони, як правило, були організовані однаково, але тепер кожен з компонентів управлявся як незалежний сегмент, і MMU буде сигналізувати про ОС, якщо програма намагалася отримати доступ до пам'яті поза сегментом. Після того, як у вас була віртуальна пам'ять, не було потреби та бажання надавати програмі доступ до всього її адресного простору. Тож сегментам були призначені фіксовані межі.
То чому б не бажано надавати програмі доступ до повного адресного простору? Тому що ця пам’ять є "фіксацією" проти свопу; в будь-який час, можливо, доведеться записати будь-яку або всю пам'ять для однієї програми для заміни, щоб звільнити місце для пам'яті іншої програми. Якщо кожна програма потенційно може споживати 2 Гб свопу, то або вам доведеться забезпечити достатню кількість підкачки для всіх своїх програм, або ризикнути, що на дві програми знадобиться більше, ніж вони можуть отримати.
У цей момент, припускаючи достатній віртуальний адресний простір, ви можете розширити ці сегменти, якщо це потрібно, і сегмент даних (купа) насправді зростає з часом: ви починаєте з невеликого сегмента даних, і коли розподільник пам'яті вимагає більше місця, коли це потрібно. На цьому етапі за допомогою одного стека було б фізично можливо розширити сегмент стека: ОС могла захопити спробу висунути щось поза сегментом і додати більше пам’яті. Але і це не особливо бажано.
Введіть багаторізкові нитки. У цьому випадку кожна нитка має незалежний сегмент стека, знову фіксованого розміру. Але тепер сегменти викладені один за одним у віртуальний адресний простір, тому немає можливості розширити один сегмент без переміщення іншого - чого ви не можете зробити, оскільки програма потенційно матиме вказівники на пам'ять, що живе в стеку. Ви також можете залишити деякий простір між сегментами, але цей простір буде витрачений майже на всі випадки. Кращим підходом було покласти тягар на розробника програми: якщо вам справді потрібні глибокі стеки, ви можете вказати це під час створення потоку.
Сьогодні, маючи 64-розрядний віртуальний адресний простір, ми могли б створити ефективно нескінченні стеки для ефективно нескінченного числа потоків. Але знову ж таки, це не особливо бажано: майже у всіх випадках стек із перекладом вказує на помилку з вашим кодом. Надання вам стеку 1 Гб просто відкладає виявлення цієї помилки.