Объясните концепцию фрейма стека в двух словах

Кажется, что я получаю идею стека вызовов в программировании языка программирования. Но я не могу найти (возможно, я просто не искал достаточно сложно) любое достойное объяснение того, что представляет собой стек кадров.

Поэтому я хотел бы попросить кого-нибудь объяснить это мне в нескольких словах.

Ответ 1

Фрейм стека представляет собой кадр данных, который попадает в стек. В случае стека вызовов кадр стека будет представлять собой вызов функции и данные аргумента.

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

EDIT:

Существует большая разница между стеками вызовов более высокого уровня и стеком вызовов процессора.

Когда мы говорим о стеке вызовов процессора, мы говорим о работе с адресами и значениями на уровне байтов/слов в сборе или машинного кода. При разговоре о языках более высокого уровня есть "стеки вызовов", но они являются инструментом отладки/выполнения, управляемым средой выполнения, поэтому вы можете регистрировать ошибки, которые поступили неправильно с вашей программой (на высоком уровне). На этом уровне часто известны такие вещи, как номера строк, имена методов и классов. К тому времени, когда процессор получает код, он не имеет абсолютно никакого понятия об этих вещах.

Ответ 2

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

Позвольте мне объяснить, как работает стек:

Сначала вы должны знать, как хранить функции в стеке:

Кучи хранят значения динамического выделения памяти. Стек хранить автоматическое размещение и удаление значений.

enter image description here

Давайте разберемся с примером:

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)

Теперь разберитесь в частях этой программы:

enter image description here

Теперь давайте посмотрим, что такое стек и что такое части стека:

enter image description here

Выделение стека:

Помните одну вещь: если какая-либо функция получит "return", независимо от того, загрузила ли она все свои локальные переменные или что-то, что она немедленно вернет из стека, будет его фреймом стека. Это означает, что когда любая рекурсивная функция получает базовое условие, и мы ставим return после базового условия, чтобы базовое условие не дожидалось загрузки локальных переменных, находящихся в "остальной" части программы, она немедленно возвращает текущий кадр из стека и теперь, если один кадр возвращать следующий кадр в записи активации. Смотрите это на практике:

enter image description here

Распределение блока:

Так что теперь, когда функция находит оператор возврата, она удаляет текущий кадр из стека.

при возврате из стека значение вернется в обратном порядке, в котором они размещены в стеке.

enter image description here

Ответ 3

Быстрая обертка. Может быть, у кого-то есть лучшее объяснение.

Стек вызовов состоит из 1 или нескольких кадров стека. Каждый кадр стека соответствует вызову функции или процедуры, которая еще не завершилась возвратом.

Чтобы использовать фрейм стека, поток поддерживает два указателя, один называется указателем стека (SP), а другой называется указателем кадра (FP). SP всегда указывает на "вершину" стека, а FP всегда указывает на "верх" кадра. Кроме того, поток также поддерживает программный счетчик (ПК), который указывает на следующую команду, которая должна быть выполнена.

В стеке хранятся следующие данные: локальные переменные и временные параметры, фактические параметры текущей команды (процедура, функция и т.д.)

Существуют различные соглашения об уходе за очисткой стека.

Ответ 4

"Стек вызова состоит из кадров стека..." - Wikipedia

Фрейм стека - это вещь, которую вы кладете в стек. Это структуры данных, которые содержат информацию о подпрограммах для вызова.

Ответ 5

У программистов могут быть вопросы о кадрах стека не в широком смысле (что это единственный объект в стеке, который обслуживает только один вызов функции и сохраняет обратный адрес, аргументы и локальные переменные), но в узком смысле - когда термин stack frames упоминается в контексте параметров компилятора.

Имел ли это значение автор вопроса или нет, но концепция фрейма стека с точки зрения параметров компилятора является очень важной проблемой, не затронутой другими ответами здесь.

Например, компилятор Microsoft Visual Studio 2015 C/С++ имеет следующий параметр, относящийся к stack frames:

  • /Oy (Бездействие кадра)

GCC имеет следующее:

  • -fomit-frame-pointer (Не держите указатель кадра в регистре для функций, которые ему не нужны. Это позволяет избежать инструкций по сохранению, настройке и восстановлению указателей кадров, а также делает доступным дополнительный регистр во многих функциях)

Компилятор Intel С++ имеет следующее:

  • -fomit-frame-pointer (Определяет, используется ли EBP в качестве универсального регистра при оптимизации)

который имеет следующий псевдоним:

  • /Оу

Delphi имеет следующую опцию командной строки:

  • - $W + (Создание фреймов стека)

В этом конкретном смысле, с точки зрения компиляторов, фрейм стека - это всего лишь код входа и выхода для подпрограммы, который подталкивает привязку к стеку, который также может использоваться для отладки и обработки исключений. Средства отладки могут сканировать данные стека и использовать эти привязки для обратного трассировки при размещении call sites в стеке, т.е. Отображать имена функций в том порядке, в котором они были названы иерархически. Для архитектуры Intel это значение push ebp; mov ebp, esp или enter для ввода и mov esp, ebp; pop ebp или leave для выхода.

Вот почему очень важно понять для программиста, что такое фрейм стека, когда дело доходит до параметров компилятора, потому что компилятор может контролировать, сгенерировать этот код или нет.

В некоторых случаях кадр стека (код ввода и выхода для подпрограммы) может быть опущен компилятором, и переменные будут напрямую доступны через указатель стека (SP/ESP/RSP), а не удобный указатель базы (ВР/ESP/РСП). Условия отсутствия кадров стека, например:

  • функция является функцией листа (т.е. конечной сущностью, которая не вызывает другие функции);
  • нет попыток try/finally или try/except или подобных конструкций, то есть исключений не используется;
  • в стеке не вызывается никаких процедур с исходящими параметрами;
  • функция не имеет параметров;
  • функция не имеет встроенного ассемблерного кода;
  • и т.д...

Опускание фреймов стека (код входа и выхода для подпрограммы) может сделать код меньше и быстрее, но это также может отрицательно повлиять на способность отладчиков возвращать данные в стеке и отображать их для программиста. Это параметры компилятора, которые определяют, в каких условиях функция должна иметь код входа и выхода, например: (a) всегда, (b) никогда, (c) при необходимости (с указанием условий).

Ответ 6

Кадр стека - это упакованная информация, связанная с вызовом функции. Эта информация обычно включает аргументы, переданные th функции, локальные переменные и где возвращаться после завершения. Активация - другое имя для фрейма стека. Макет фрейма стека определяется в ABI производителем, и каждый компилятор, поддерживающий ISA, должен соответствовать этому стандарту, однако схема компоновки может быть зависимой от компилятора. Как правило, размер фрейма стека не ограничен, но существует концепция, называемая "красная/защищенная зона", позволяющая выполнять системные вызовы... и т.д. Без вмешательства в стек стека.

Всегда есть SP, но на некоторых ABI (например, ARM и PowerPC) FP является необязательным. Аргументы, которые необходимо поместить в стек, могут быть смещены с использованием только SP. Является ли кадр стека для вызова функции или нет, зависит от типа и количества аргументов, от локальных переменных и от того, как обычно обращаются к локальным переменным. В большинстве ISA используются регистры, и если есть больше аргументов, чем регистров, посвященных аргументам передачи, они помещаются в стек (например, x86 ABI имеет 6 регистров для передачи целочисленных аргументов). Следовательно, иногда некоторым функциям не нужен стек стека, который должен быть помещен в стек, только адрес возврата помещается в стек.