почему windows использует стеки для хранения локальных переменных?


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

У меня есть еще несколько вопросов о том же самом,

Вопрос 1) как локальные переменные ссылаются из части инструкции. Рассмотрим NewThreadFunc-это функция, которая вызывается функцией createThread.

DWORD WINAPI NewThreadFunc(PVOID p_pParam)
{
int l_iLocalVar1 = 10;
int l_iLocalVar2 = 20;

int l_iSumLocalVar = l_iLocalVar1 + l_iLocalVar2;
}

Стек для этого потока будет выглядеть следующим образом,

| p_pParam       |
| NewThreadFunc()|
| 10             |
| 20             |
| 30             |
|                |
.
.
.

Теперь мой вопрос, при выполнении этой функции, как процессор будет знать адрес локальных переменных, (int l_iSumLocalVar, l_iLocalVar1 и l_iLocalVar2)? Эти переменные не являются указателями на то, что они хранят адрес, из которого они должны извлечь значение. Мой вопрос заключается в том, чтобы записать стек выше.

Вопрос 2) Если эта функция далее вызывает любую другую функцию, как стек будет вести себя с ней? Как я знаю, стек будет разделен на себя дальше. Если это правда ... как локальные переменные вызываемой функции скрываются от вызываемой функции. В основном, как локальные переменные поддерживают правила области?

Я знаю, что это могут быть очень простые вопросы, но некоторые из них я не мог придумать ответа на них.
4 3

4 ответа:

Во-первых, это не "Windows", которая использует стек для локальных переменных. Это не имеет абсолютно никакого отношения к" Windows " или к любой другой ОС, если на то пошло. Это делает ваш компилятор. Никто не заставляет компилятор использовать системный стек для этой цели, но обычно это самый простой и эффективный способ реализации локальных переменных.

Во-вторых, компиляторы используют стеки для хранения локальных переменных (будь то системные стеки или реализованные компилятором стеки) просто потому, что стекоподобное хранилище очень точно соответствует семантике локальных переменных, заданной языком. Длительность хранения локальных переменных определяется их декларативными областями (блоками), которые строго вложены друг в друга. Это сразу же означает, что длительность хранения локальных переменных следует принципу ЛИФО: последний вход-первый выход. Итак, использование стека-структуры данных LIFO-для выделения объектов с длительностью хранения LIFO-это первое и самое естественное, что приходит на ум. ум.

Локальные переменные обычно адресуются по ихсмещению от начала текущего активного кадра стека. Компилятор знает точное смещение каждой локальной переменной во время компиляции. Компилятор генерирует код, который выделит кадр стека для текущей функции путем: 1) запоминания текущего положения указателя стека при вводе функции (допустим, он запоминается в регистре R1) и 2) перемещения текущего указателя стека на величину необходимо хранить все локальные переменные функции. Как только фрейм стека будет выделен таким образом, ваши локальные переменные l_iLocalVar1, l_iLocalVar2 и l_iSumLocalVar будет просто доступен через адреса R1 + 6, R1 + 10 и R1 + 14 (я использовал произвольные смещения). Другими словами, локальные переменные недоступны для определенных значений адресов, так как эти адреса неизвестны во время компиляции. Вместо этого доступ к локальным переменным осуществляется черезвычисляемые адреса. Они рассчитываются как некоторая база времени выполнения значение адреса + некоторое значение смещения во время компиляции.

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

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

Почему стек используется для локальных переменных?

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

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