Стек -Спосіб організації пам'яті.
У цій пам'яті зберігаються інформація про послідовність викликів виконуються зараз функцій, локальні змінні і фрейми обробки винятків.
Строго кажучи, працювати зі стеком потоку можна на рівні повних слів процесора. Іншими словами, у процесора є команди "покласти в стек повне слово" і "дістати з стека повне слово". Але найчастіше мови високого рівня працюють зі стеком на рівні фреймів.
Фрейм стека - це блок даних, що описують інформацію про хід роботи однієї підпрограми, що виконується в даний момент. У нього входять:
Розмір фрейму стека може динамічно змінюватися в ході роботи програми до тих пір поки він в стеці залишається верхнім. Крім того, в деяких мовах програмування є спеціальні функції, які не створюють своїх фреймів, а змінюють батьківський - так, на С / С ++ цим "грішать" setjmp / longjmp і alloca
Взагалі, фрейм стека створюється самою підпрограмою на початку її роботи (це називається "пролог" підпрограми) і знищується в кінці (як називається - не знаю, "епілог"?). Але, наприклад, на асемблері програміст сам визначає поведінку підпрограми, та й на мовах високого рівня є можливість відмовитися від прологу (наприклад, __declspec (naked) в Visual C / C ++), так що створювати повний фрейм стека чи ні - визначається рішенням програміста.
Але є два елементи, які програмісту непідвладні - це перший і другий пункти, оскільки в стек вони кладуться не викликає, а викликає підпрограмою (ну ще б, звідки викликається підпрограмі про них взагалі дізнатися, як не з стека). Подробиці передачі цих двох елементів визначаються такою річчю, як угода про виклик.
Так, угода про виклик cdecl, що застосовується для функцій мов C і C ++, означає, що параметри в стек кладуться в зворотному порядку, а витягуються викликає підпрограмою. Це дозволяє використовувати підпрограми зі змінним числом аргументів, оскільки в такому випадку перший параметр, який відповідає за кількість аргументів, виявляється ближче всього до вершини стека, а, значить, відстань між ним і вершиною стека постійне. Це дозволяє викликається підпрограмі його знайти.
Як я вже сказав на самому початку, стеки існують не у процесів, а у потоків. Це пов'язано з тим, що для різних потоків ланцюжок викликів підпрограм може бути абсолютно різною. Це не є незручністю, скоріше це навіть добре, оскільки дозволяє для реалізації перемикання потоків просто підміняти поточний покажчик вершини стека, підміняючи таким чином весь стек викликів. Решта величини (наприклад, регістри процесора) явно зберігати і підміняти не треба - достатньо зберегти їх в стеку, а потім відновити. Таким чином, якщо відкинути мішуру з маркерів безпеки, блокувань і іншого, то на принциповому рівні потік - це всього лише збережений покажчик на вершину стека (в процесорах x86 - регістр esp або реєстрова пара ss: esp)