2012-02-08 2 views
1

Я в замешательстве. Выполняется ли распределение автоматических, статических и глобальных переменных во время компиляции или времени выполнения?Выделение памяти переменных

Я знаю, что во время компиляции исходный код переводится на машинный язык.

Когда компилятор находит инструкцию типа int a;, он записывает инструкцию. Выполняются ли какие-либо дополнительные действия, такие как распределение памяти, во время компиляции?

Что произойдет, если будет выполнен .exe-файл?

Независимо от того, будет ли компьютер (ОС) или компилятор выделять достаточную память для хранения целого числа во время выполнения или времени компиляции.

Также говорится, что адрес глобальной переменной является константой времени компиляции. Что это значит? Пожалуйста, помогите решить каждый вопрос, особенно последний.

+1

Объявление типа 'int a;' не соответствует непосредственно машинной инструкции. –

+0

Это домашнее задание? – Francois

+0

, который не является частью моей домашней работы. Вопрос: на мой взгляд, старое обучение сталкивается с новым. Также я всегда это делаю Google до тех пор, пока не разойдусь –

ответ

6

Статические глобальные переменные выделяют ресурсы памяти либо во время компиляции, либо во время выполнения. Это зависит от того, являются ли статические переменные нулевыми или инициализированы исходными значениями.Например, код, как

//global variable with internal linkage 
static int array[100]; 

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

//global variable with internal linkage 
static int array[100] = { 1, 2, 3}; 

займет место в исполняемом файле, поскольку оно инициализируется постоянными значениями во время компиляции. Таким образом, компилятор будет испускать код в разделе data файла сборки, который он генерирует, который выделяет хранилище для массива. Затем компоновщик правильно компонует разделы раздела данных и кода всех файлов сборки, которые связаны с окончательным исполняемым файлом. Когда ОС загружает исполняемый файл в память, память для массива уже является частью памяти исполняемого файла «foot-print».

Автоматические переменные, поскольку они выделены в стеке во время выполнения кода, выделяются во время выполнения.

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

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

+0

, вы говорите только о глобальной переменной с внутренней связью. Что происходит с глобальными переменными с внешними linkage –

+0

То же самое по существу ... внутренняя и внешняя связь просто определяют видимость расположения памяти из другого модуля кода. – Jason

+0

Вы имеете в виду тип константы-заполнителя (адрес будет постоянным при предоставлении ОС) присваивается глобальным переменным –

0

У вас есть куча вопросов здесь. В C у вас есть память стека и память кучи. Глобалы находятся в куче. Все переменные non malloc, которые не являются глобальными, находятся в стеке. Думайте о стеке памяти как о памяти, которую вы создаете внутри своих функций. Каждый вызов функции добавляет еще один слой в ваш стек. Когда функция возвращается, возвращается немолочная память, которая была выделена внутри этой функции. Место хранения глобальной переменной никогда не изменяется, поэтому его позиция может быть статичной во время компиляции.

0

Когда компилятор находит заявление как Int А ;, он записывает instruction.Does любые дополнительные вещи случаются, как распределение памяти в время компиляции?

Да, пространство зарезервировано для переменной в стеке.

Что произойдет, если будет выполнен .exe-файл?

Слишком длинный, чтобы ответить на него здесь. Ограничьте свой вопрос.

Будет ли компьютер (os) или компилятор выделять достаточную память , удерживая целое число во время выполнения или время компиляции.

Зависит от того, как вы выделяете память на свой код.

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

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

0

Когда компилятор находит инструкцию int a; в функции, он пишет что-то вроде sub esp,sizeof(int), а когда программа запускается и получает эту строку, она выделяет память.

Если это глобальная переменная, компилятор записывает инструкцию resb, в которой говорится, что ОС выделяет память при загрузке программы.

1

Это зависит от типа переменного:

  • стек переменных делается во время выполнения (хотя их размера знать во время компиляции, память стека только зарезервирована на входе функции, что делает его во время выполнения распределения). есть также специальное предостережение, alloca выделяет из стека во время выполнения, хотя оно похоже на его динамическую память кучи.

  • Переменные кучи выделяются во время выполнения, обычно через new/malloc, однако хранилище указателей все еще может находиться в стеке.

  • глобальные и статические переменные выделяются несколькими способами. инициализированные будут выделяться в двоичном виде компилятором с их начальным значением (или инициализатор будет вызываться при запуске для объектов).неинициализированные данные будут распределены через загрузчик ОС, читая PE, поэтому данные разделяются между различными сегментами, такими как .rdata, .data & .bss.

Теперь с переменными, которые являются глобальными/статическими, компилятор может связать относительный или предпочитаемые постоянный адрес для них, потому что они выделяются в двоичном виде.

1

компилятор генерирует объектный файл (.obj под Windows, .o под Unix), который содержит больше, чем просто машинные команды, а не все конструкции в C++ приведет к машинным командам. Когда происходит выделение памяти (формально, по крайней мере), не указано. На практике , так как число автоматических и динамических объектов неизвестно при компиляции времени (так как функции могут быть рекурсивными), их можно выделить только в времени компиляции, и компилятор будет генерировать код для этого (хотя он обычно выделяет все автоматических переменных в функции с одной или двумя инструкциями в верхней части функции). С с другой стороны, компилятор точно знает, сколько объектов со статическим будет существовать. Все реализации, которые я знаю с помощью , генерируют записи загрузчика в объектном файле, что в итоге приводит к тому, что системный загрузчик выделяет их как часть исходного изображения процесса при загрузке программы; в загруженной программе нет кода, который выделяет их. (Если инициализация не является статической, будет введен код , который их инициализирует.)

Смежные вопросы