Відповіді:
Кадр стека - це кадр даних, який висувається на стек. У випадку стека виклику кадр стека представлятиме функціональний виклик та його аргументаційні дані.
Якщо я добре пам'ятаю, повернення функції спочатку висувається на стек, а потім аргументи та простір для локальних змінних. Разом вони роблять "кадр", хоча це, ймовірно, залежить від архітектури. Процесор знає, скільки байтів знаходиться в кожному кадрі, і відповідно переміщує покажчик стека, коли кадри висуваються і вискакують зі стека.
Існує велика різниця між стеками викликів вищого рівня та стеком викликів процесора.
Коли ми говоримо про стек викликів процесора, ми говоримо про роботу з адресами та значеннями на рівні байтів / слів у складанні або машинному коді. Існують "стеки викликів", коли мова йде про мови вищого рівня, але вони є інструментом налагодження / виконання, керованим середовищем виконання, щоб ви могли зафіксувати те, що пішло не так у вашій програмі (на високому рівні). На цьому рівні часто відомі такі речі, як номери рядків, назви методів та класів. На той момент, коли процесор отримує код, він абсолютно не має поняття про ці речі.
Якщо ви дуже добре розумієте стек, то зрозумієте, як працює пам'ять у програмі, і якщо ви розумієте, як працює пам'ять у програмі, ви зрозумієте, як зберігається функція в програмі, і якщо ви розумієте, як зберігається функція в програмі, ви зрозумієте, як працює рекурсивна функція і якщо ви розумієте, як працює рекурсивна функція, ви зрозумієте, як працює компілятор, і якщо ви зрозумієте, як працює компілятор, ваш розум буде працювати як компілятор, і ви легко налагодите будь-яку програму
Дозвольте мені пояснити, як працює стек:
Спочатку ви повинні знати, як представлені функції в стеці:
Купа зберігає динамічно виділені значення.
Стек зберігає значення автоматичного розподілу та видалення.
Розберемося на прикладі:
def hello(x):
if x==1:
return "op"
else:
u=1
e=12
s=hello(x-1)
e+=1
print(s)
print(x)
u+=1
return e
hello(4)
Тепер зрозумійте частини цієї програми:
Тепер давайте розберемося, що таке стек і що це частини стека:
Виділення стека:
Пам’ятайте одне: якщо умова повернення будь-якої функції задовольняється, незалежно від того, завантажила вона локальні змінні чи ні, вона негайно повернеться із стека разом із рамкою стека. Це означає, що всякий раз, коли будь-яка рекурсивна функція задовольняє базову умову, і ми ставимо повернення після базової умови, базова умова не чекатиме завантаження локальних змінних, які знаходяться в іншій частині програми. Він негайно поверне поточний кадр із стека, за яким наступний кадр тепер знаходиться в записі активації.
Дивіться це на практиці:
Розподіл блоку:
Тому тепер, коли функція стикається з оператором return, вона видаляє поточний кадр зі стека.
Повертаючись із стека, значення повертаються у зворотному порядку, у якому вони були розподілені у стеці.
hello()
рекурсивно викликав, hello()
який потім (знову) рекурсивно викликав hello()
, а глобальний кадр - це оригінальна функція, яка називається першою hello()
?
Швидке обгортання. Можливо, хтось має краще пояснення.
Стек виклику складається з 1 або багатьох декількох кадрів стека. Кожному фрейму стека відповідає виклик функції або процедури, яка ще не закінчилася поверненням.
Для використання кадру стека нитка зберігає два вказівники, один називається покажчиком стека (SP), а другий називається покажчиком кадру (FP). SP завжди вказує на "верх" стека, а FP завжди вказує на "верх" кадру. Крім того, потік також підтримує лічильник програм (ПК), який вказує на наступну інструкцію, яку потрібно виконати.
На стеку зберігаються: локальні змінні та часові часописи, фактичні параметри поточної інструкції (процедура, функція тощо)
Існують різні умови виклику щодо очищення штабеля.
"Стек виклику складається з кадру стека ..." - Вікіпедія
Рамка стека - це річ, яку ви кладете на стек. Це структури даних, які містять інформацію про підпрограми для виклику.
Програмісти можуть мати питання щодо фреймів стека не в широкому терміні (що це окрема суть у стеку, яка обслуговує лише один виклик функції і зберігає зворотну адресу, аргументи та локальні змінні), але у вузькому сенсі - коли термін stack frames
згадується в контекст параметрів компілятора.
Має на увазі автор запитання чи ні, але концепція кадру стека з точки зору варіантів компілятора є дуже важливим питанням, не охопленим іншими відповідями тут.
Наприклад, компілятор Microsoft Visual Studio 2015 C / C ++ має такий варіант, пов’язаний із stack frames
:
GCC мають наступне:
Компілятор Intel C ++ має такі характеристики:
який має такий псевдонім:
У Delphi є такий варіант командного рядка:
У цьому конкретному сенсі, з точки зору компілятора, стековий кадр - це лише код входу та виходу для підпрограми , який підштовхує якір до стеку - який також може використовуватися для налагодження та для обробки винятків. Інструменти для налагодження можуть сканувати дані стека та використовувати ці якорі для зворотного call sites
проходження , розміщуючи в стеку, тобто для відображення назв функцій у тому порядку, який вони були названі ієрархічно. Для архітектури Intel це - push ebp; mov ebp, esp
або enter
для входу, mov esp, ebp; pop ebp
або leave
для виходу.
Ось чому дуже важливо зрозуміти програмісту, що таке кадр стека, коли мова йде про параметри компілятора - адже компілятор може контролювати, генерувати цей код чи ні.
У деяких випадках кадр стека (код входу та виходу для підпрограми) може бути опущений компілятором, і до змінних буде доступ безпосередньо через вказівник стека (SP / ESP / RSP), а не зручний базовий покажчик (BP / ESP / RSP). Умови опущення рамки стека, наприклад:
Опущення кадрів стека (код входу та виходу для звичайної програми) може зробити код меншим та швидшим, але це також може негативно вплинути на здатність налагоджувачів відновлювати дані в стеку та відображати їх програмісту. Це варіанти компілятора, які визначають, за яких умов функція повинна мати код входу та виходу, наприклад: (a) завжди, (b) ніколи, (c) за потреби (із зазначенням умов).
Кадр стека - це упакована інформація, пов'язана з викликом функції. Ця інформація, як правило, включає аргументи, передані до функції, локальні змінні та куди повернутися після закінчення. Запис активації - інша назва кадру стека. Макет кадру стека визначається в ABI виробником, і кожен компілятор, що підтримує ISA, повинен відповідати цьому стандарту, однак схема компонування може залежати від компілятора. Як правило, розмір кадру стека не обмежений, але існує концепція, яка називається "червона / захищена зона", яка дозволяє системним викликам ... тощо виконувати, не заважаючи кадру стека.
SP завжди є, але на деяких ABI (наприклад, ARM та PowerPC) FP необов’язковий. Аргументи, які потрібно було розмістити на стеку, можна компенсувати лише за допомогою SP. Чи буде створений кадр стека для виклику функції чи ні, залежить від типу та кількості аргументів, локальних змінних та способу доступу до локальних змінних. У більшості ISA, по-перше, використовуються регістри, і якщо аргументів більше, ніж регістри, призначені для передачі аргументів, вони розміщуються в стеку (наприклад, x86 ABI має 6 регістрів для передачі цілих аргументів). Отже, іноді деяким функціям не потрібен кадр стека, щоб розміщувати його на стеку, просто повернення адреси висувається на стек.