Пам'ять, виділена під час компіляції, означає, що компілятор вирішує в час компіляції, де певні речі будуть розподілені всередині карти пам'яті процесу.
Наприклад, розглянемо глобальний масив:
int array[100];
Компілятор знає в час компіляції розмір масиву і розмір int
, тому він знає весь розмір масиву під час компіляції. Також глобальна змінна за замовчуванням має тривалість статичної пам’яті: вона розподіляється в області статичної пам’яті простору технологічної пам’яті (розділ .data / .bss). Враховуючи цю інформацію, компілятор вирішує під час компіляції, в якій адресі цієї статичної області пам'яті буде масив .
Звичайно, що адреси пам'яті - це віртуальні адреси. Програма передбачає, що у неї є власний простір пам'яті (наприклад, від 0x00000000 до 0xFFFFFFFF). Ось чому компілятор міг робити припущення типу "Гаразд, масив буде за адресою 0x00A33211". Під час виконання ці MMU та ОС перетворюють адреси на реальні / апаратні адреси.
Значення ініціалізованих речей статичного зберігання дещо відрізняються. Наприклад:
int array[] = { 1 , 2 , 3 , 4 };
У нашому першому прикладі компілятор лише вирішив, куди буде виділено масив, зберігаючи цю інформацію у виконуваному файлі.
У випадку ініціалізованих значень компілятор також вводить початкове значення масиву у виконуваний файл і додає код, який повідомляє завантажувачу програми, що після розподілу масиву при запуску програми масив повинен бути заповнений цими значеннями.
Ось два приклади збірки, згенерованої компілятором (GCC4.8.1 з ціллю x86):
Код C ++:
int a[4];
int b[] = { 1 , 2 , 3 , 4 };
int main()
{}
Вихідна збірка:
a:
.zero 16
b:
.long 1
.long 2
.long 3
.long 4
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
Як бачите, значення безпосередньо вводяться в збірку. У масиві a
компілятор генерує нульову ініціалізацію 16 байтів, оскільки Стандарт говорить, що статичні збережені речі повинні бути ініціалізовані до нуля за замовчуванням:
8.5.9 (Ініціалізатори) [Примітка]:
Кожен об'єкт статичної тривалості зберігання нульово ініціалізується при запуску програми до того, як відбудеться будь-яка інша ініціалізація. У деяких випадках додаткова ініціалізація проводиться пізніше.
Я завжди пропоную людям розібрати свій код, щоб побачити, що компілятор насправді робить з кодом C ++. Це стосується класів / тривалості зберігання (як це питання) до розширених оптимізацій компілятора. Ви можете доручити своєму компілятору створити збірку, але є чудові інструменти, щоб зробити це в Інтернеті дружньо. Мій улюблений - GCC Explorer .