Pamięć przydzielona w czasie kompilacji oznacza, że kompilator rozwiązuje problem w czasie kompilacji, w którym pewne rzeczy zostaną przydzielone w mapie pamięci procesu.
Na przykład rozważmy tablicę globalną:
int array[100];
Kompilator wie w czasie kompilacji rozmiar tablicy i rozmiar an int
, więc zna cały rozmiar tablicy w czasie kompilacji. Również zmienna globalna ma domyślnie statyczny czas trwania: jest alokowana w obszarze pamięci statycznej obszaru pamięci procesu (sekcja .data / .bss). Biorąc pod uwagę te informacje, kompilator decyduje podczas kompilacji, w jakim adresie tego statycznego obszaru pamięci będzie tablica .
Oczywiście te adresy pamięci są adresami wirtualnymi. Program zakłada, że ma własną całą przestrzeń pamięci (na przykład od 0x00000000 do 0xFFFFFFFF). Dlatego kompilator mógł wykonać założenia typu „OK, tablica będzie miała adres 0x00A33211”. W czasie wykonywania te adresy są tłumaczone na adresy rzeczywiste / sprzętowe przez MMU i system operacyjny.
Wartość zainicjowanej wartości statycznej pamięci masowej jest nieco inna. Na przykład:
int array[] = { 1 , 2 , 3 , 4 };
W naszym pierwszym przykładzie kompilator zdecydował tylko, gdzie tablica zostanie przydzielona, przechowując te informacje w pliku wykonywalnym.
W przypadku rzeczy zainicjowanych wartością, kompilator również wstrzykuje wartość początkową tablicy do pliku wykonywalnego i dodaje kod, który mówi programowi ładującemu, że po przydzieleniu tablicy przy uruchomieniu programu tablica powinna zostać wypełniona tymi wartościami.
Oto dwa przykłady zestawu wygenerowanego przez kompilator (GCC4.8.1 z celem x86):
Kod C ++:
int a[4];
int b[] = { 1 , 2 , 3 , 4 };
int main()
{}
Zespół wyjściowy:
a:
.zero 16
b:
.long 1
.long 2
.long 3
.long 4
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
Jak widać, wartości są wprowadzane bezpośrednio do zespołu. W tablicy a
kompilator generuje zerową inicjalizację 16 bajtów, ponieważ Standard mówi, że statyczne przechowywane rzeczy powinny być domyślnie inicjowane do zera:
8.5.9 (Inicjatory) [Uwaga]:
Każdy obiekt o statycznym czasie trwania przechowywania jest inicjowany do zera podczas uruchamiania programu przed jakąkolwiek inną inicjalizacją. W niektórych przypadkach dodatkowa inicjalizacja jest wykonywana później.
Zawsze sugeruję ludziom rozmontowanie kodu, aby zobaczyć, co kompilator naprawdę robi z kodem C ++. Dotyczy to klas pamięci / czasu trwania (jak to pytanie) do zaawansowanych optymalizacji kompilatora. Możesz poinstruować kompilator, aby wygenerował asemblację, ale w Internecie są wspaniałe narzędzia do tego w przyjazny sposób. Moim ulubionym jest GCC Explorer .