Zur Kompilierungszeit zugewiesener Speicher bedeutet, dass der Compiler zur Kompilierungszeit aufgelöst wird, wenn bestimmte Dinge in der Prozessspeicherzuordnung zugewiesen werden.
Betrachten Sie beispielsweise ein globales Array:
int array[100];
Der Compiler kennt zur Kompilierungszeit die Größe des Arrays und die Größe eines int
, sodass er zur Kompilierungszeit die gesamte Größe des Arrays kennt. Außerdem hat eine globale Variable standardmäßig eine statische Speicherdauer: Sie wird im statischen Speicherbereich des Prozessspeicherbereichs (Abschnitt .data / .bss) zugewiesen. Angesichts dieser Informationen entscheidet der Compiler während der Kompilierung, in welcher Adresse dieses statischen Speicherbereichs sich das Array befindet .
Natürlich sind diese Speicheradressen virtuelle Adressen. Das Programm geht davon aus, dass es über einen eigenen Speicherplatz verfügt (z. B. von 0x00000000 bis 0xFFFFFFFF). Aus diesem Grund könnte der Compiler Annahmen wie "Okay, das Array befindet sich unter der Adresse 0x00A33211" treffen. Zur Laufzeit werden diese Adressen von der MMU und dem Betriebssystem in echte / Hardwareadressen übersetzt.
Wertinitialisierte statische Speicher Dinge sind ein bisschen anders. Beispielsweise:
int array[] = { 1 , 2 , 3 , 4 };
In unserem ersten Beispiel hat der Compiler nur entschieden, wo das Array zugewiesen wird, und diese Informationen in der ausführbaren Datei gespeichert.
Bei wertinitialisierten Dingen fügt der Compiler auch den Anfangswert des Arrays in die ausführbare Datei ein und fügt Code hinzu, der dem Programmlader mitteilt, dass das Array nach der Arrayzuweisung beim Programmstart mit diesen Werten gefüllt werden soll.
Hier sind zwei Beispiele für die vom Compiler generierte Assembly (GCC4.8.1 mit x86-Ziel):
C ++ - Code:
int a[4];
int b[] = { 1 , 2 , 3 , 4 };
int main()
{}
Ausgabebaugruppe:
a:
.zero 16
b:
.long 1
.long 2
.long 3
.long 4
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
Wie Sie sehen können, werden die Werte direkt in die Baugruppe eingefügt. Im Array a
generiert der Compiler eine Nullinitialisierung von 16 Byte, da der Standard vorschreibt, dass statisch gespeicherte Dinge standardmäßig auf Null initialisiert werden sollten:
8.5.9 (Initialisierer) [Hinweis]:
Jedes Objekt mit statischer Speicherdauer wird beim Programmstart auf Null initialisiert, bevor eine andere Initialisierung stattfindet. In einigen Fällen erfolgt die zusätzliche Initialisierung später.
Ich empfehle immer, den Code zu zerlegen, um zu sehen, was der Compiler wirklich mit dem C ++ - Code macht. Dies gilt von Speicherklassen / Dauer (wie diese Frage) bis zu erweiterten Compileroptimierungen. Sie könnten Ihren Compiler anweisen, die Assembly zu generieren, aber es gibt wunderbare Tools, um dies im Internet auf freundliche Weise zu tun. Mein Favorit ist GCC Explorer .