#c #memory #scope #static #auto
#c #память #область #статический #авто
Вопрос:
Если мы говорим о статическом распределении памяти, говорят, что оно выделяется во время компиляции, но на самом деле компилятор просто обрабатывает это выделение памяти, и оно фактически выделяется только при запуске программы. Например, компилятор может создать большой data
раздел в скомпилированном двоичном файле, и когда программа загружается в память, адрес в data
сегменте программы будет использоваться в качестве местоположения выделенной памяти.
Если я говорю об автоматическом распределении памяти, оно выделяется, когда элемент управления входит в новую область. Теперь я сомневаюсь, что в этом случае также появляется компилятор и передает некоторые виртуальные адреса в скомпилированный двоичный файл, который позже становится адресами фактической выделенной памяти во время выполнения, или эта память выделяется только во время выполнения без какой-либо роли компилятора, точно так же, как выделяется динамическая память?
Что, если у меня есть какая-то локальная переменная, например:
int a = 10;
Будет ли у него выделение времени компиляции или времени выполнения?
Комментарии:
1. Компилятор может оптимизировать эту переменную (без выделения памяти), использовать регистр только для этой переменной (без выделения памяти) или генерировать инструкции для выделения для нее места в стеке.
Ответ №1:
Автоматическое выделение происходит во время выполнения, хотя характер его очень специфичен для системы. Автоматические переменные продолжительности хранения могут оказаться в регистрах, в стеке или полностью оптимизированы.
В случае, если они попадают в стек, компилятор создает локальное смещение области видимости для функции, в которой выделена переменная. То есть переменная может называться как SP 8
или что-то подобное, где SP — указатель стека. Которое, в свою очередь, может содержать любое значение при вводе функции — компилятор или машинный код не знают или не заботятся об этом, поэтому существуют переполнения стека.
Вы можете найти это полезным: что выделяется в стеке и куче ?.
Комментарии:
1. Если я все правильно понял, это означает, что компилятор создаст смещения области видимости, но фактическое выделение для них будет выполняться только во время выполнения?
2. @LocalHost Да, они выделяются либо с помощью специальных push-инструкций, либо как часть стекового фрейма, в зависимости от ISA и ABI.
Ответ №2:
Локальные переменные помещаются в стек, когда они хранятся в памяти.
Как правило, общее требование к размеру стека для функции вычисляется во время компиляции. Затем, при вводе функции, указатель стека корректируется вниз для всего размера стека функции — стек обычно растет от более высокого адреса к более низкому адресу.
Каждой локальной переменной присваивается адрес в текущем фрейме стека, и к ним обычно обращаются с помощью инструкций доступа к памяти, которые считывают или записывают память с заданным смещением к текущему указателю стека.
Однако в оптимизированных сборках локальные переменные часто также хранятся в регистрах процессора (когда доступно достаточно регистров) и не обязательно хранятся в памяти вообще. Цель этого — избежать обращений к памяти, чтобы ускорить программу. Распределение регистров (компилятор выбирает, какие переменные хранить в регистрах и какой регистр использовать для какой переменной) зависит от большого количества черной магии, которую выполняет компилятор, анализируя время жизни переменной и сколько она используется.