it-swarm.com.de

Wann werden statische und globale Variablen initialisiert?

In C++ weiß ich, dass static und global Objekte vor der main-Funktion erstellt werden. Wie Sie wissen, gibt es in C keinen solchen Code initialization procedure vor main.

Zum Beispiel in meinem Code:

int global_int1 = 5;
int global_int2;
static int static_int1 = 4;
static int static_int2;
  • Wann sind diese vier Variablen initialisiert?
  • Wo werden Werte für die Initialisierung wie 5 und 4 während der Übersetzung gespeichert? Wie werden sie bei der Initialisierung verwaltet?

EDIT:
Klarstellung der zweiten Frage. 

  • In meinem Code verwende ich 5, um initialisierenglobal_int1, also wie kann der Compiler zuweisen5global_int zuweisen? Beispielsweise speichert der Compiler den 5-Wert zum Beispiel irgendwo (d. H. In einer Tabelle) und erhält diesen Wert, wenn die Initialisierung beginnt.
  • Was "Wie man sie bei der Initialisierung verwaltet?" Ist wirklich vage und ich selbst kann noch nicht interpretieren. Manchmal ist es nicht leicht, eine Frage zu erklären. Übersehen Sie es, da ich die Frage noch nicht vollständig beherrscht habe.
28
Zachary

Unter statischen und globalen Objekten gehe ich davon aus, dass Sie Objekte mit der statischen Lebensdauer von ____ im Namespace-Bereich definieren. Wenn solche Objekte mit lokalem Bereich definiert sind, unterscheiden sich die Regeln geringfügig. 

Formal initialisiert C++ solche Variablen in drei Phasen: 1. Nullinitialisierung 2. Statische Initialisierung 3. Dynamische Initialisierung. Die Sprache unterscheidet auch zwischen Variablen, die eine dynamische Initialisierung erfordern, und solchen, die eine statische Initialisierung erfordern: Alle statischen Objekte (Objekte mit statischer Lebensdauer) werden zunächst mit Null initialisiert, dann mit statischen Objekten Die Initialisierung wird initialisiert und anschließend erfolgt die dynamische Initialisierung

Als einfache erste Annäherung bedeutet dynamische Initialisierung, dass ein Code ausgeführt werden muss. In der Regel statische Initialisierung nicht. Somit:

extern int f();

int g1 = 42;    //  static initialization
int g2 = f();   //  dynamic initialization

Eine weitere Annäherung wäre, dass die statische Initialisierung __ ist. Was C unterstützt (für Variablen mit statischer Lebensdauer), dynamisch __ alles andere.

Wie der Compiler dies tut, hängt natürlich von der -Initialisierung ab, aber von plattenbasierten Systemen, auf denen die ausführbare Datei von der Festplatte in den Arbeitsspeicher geladen wird Diskette geladen und direkt vom System von der Diskette geladen. In einem klassischen Unix-System würden globale Variablen in drei "Segmente" unterteilt:

text:
Der Code wurde in einen schreibgeschützten Bereich geladen. Statische -Variablen mit `const`-Typen würden ebenfalls hier platziert werden .
daten:
Statische Variablen mit statischen Initialisierern .
bss:
Statische Variablen ohne Initialisierung (C und C++) oder mit dynamischer Initialisierung (C++). Die ausführbare Datei enthält kein Bild für dieses Segment, und das System setzt alles auf "0", bevor Ihr Code beginnt .

Ich vermute, dass viele moderne Systeme immer noch etwas ähnliches verwenden.

BEARBEITEN: 

Noch eine Bemerkung: Das oben Genannte bezieht sich auf C++ 03. Für vorhandene -Programme ändert C++ 11 wahrscheinlich nichts, aber Add constexpr (was bedeutet, dass einige benutzerdefinierte Funktionen Immer noch eine statische Initialisierung sein können) und lokale Thread-Variablen ., was eine völlig neue Dose Würmer öffnet.

21
James Kanze

Vorwort: Das Wort "statisch" hat eine große Anzahl unterschiedlicher Bedeutungen in C++. Sei nicht verwirrt.

Alle Ihre Objekte haben statische Speicherdauer . Das liegt daran, dass sie weder automatisch noch dynamisch sind. (Noch Thread-Local, obwohl Thread-Local ein bisschen wie statisch ist.)

In C++ werden statische Objekte in zwei Phasen initialisiert: statische Initialisierung und dynamische Initialisierung.

  • Für die dynamische Initialisierung muss der eigentliche Code ausgeführt werden. Dies geschieht also für Objekte, die mit einem Konstruktoraufruf beginnen oder bei denen der Initialisierer ein Ausdruck ist, der nur zur Laufzeit ausgewertet werden kann.

  • Statische Initialisierung ist, wenn der Initialisierer statisch bekannt ist und kein Konstruktor ausgeführt werden muss. (Statische Initialisierung ist entweder Nullinitialisierung oder Konstante-Initialisierung .) Dies ist der Fall für Ihre int-Variablen mit konstantem Initialisierer, und Sie sind garantiert, dass diese tatsächlich in der statischen Phase initialisiert werden.

  • (Static-Storage-Variablen mit dynamischer Initialisierung werden also statisch null initialisiert, bevor irgendetwas anderes passiert.)

Der entscheidende Punkt ist, dass die statische Initialisierungsphase überhaupt nicht "läuft". Die Daten sind von Anfang an dabei. Das bedeutet, dass es keine "Reihenfolge" oder sonstige dynamische Eigenschaften gibt, die sich auf die statische Initialisierung beziehen. Die Anfangswerte sind in Ihrer Programm-Binärdatei hartcodiert, wenn Sie möchten.

12
Kerrek SB

Wann werden diese vier Variablen initialisiert?

Wie Sie sagen, geschieht dies vor dem Programmstart, d. H. Bevor main beginnt. C gibt es nicht weiter an; In C++ geschieht dies während der statischen Initialisierungsphase vor Objekten mit komplizierteren Konstruktoren oder Initialisierern.

Wo werden Werte für die Initialisierung wie 5 und 4 während des Kompilierens gespeichert?

Normalerweise werden die Nicht-Null-Werte in einem Datensegment in der Programmdatei gespeichert, während die Null-Werte in einem Bss - Segment liegen, das gerade genügend Speicher für die Variablen reserviert. Wenn das Programm startet, wird das Datensegment in den Speicher geladen und das bss - Segment auf Null gesetzt. (Natürlich schreibt der Sprachstandard dies nicht vor, daher könnte ein Compiler etwas anderes tun, beispielsweise Code generieren, um jede Variable vor der Ausführung von main zu initialisieren.).

3
Mike Seymour

Paraphrasiert vom Standard:

Alle Variablen, die keine dynamische Speicherdauer haben, keine lokale Threadspeicherdauer haben und nicht lokal sind, haben eine statische Speicherdauer. Mit anderen Worten, alle Globals haben eine statische Speicherdauer.

Statische Objekte mit dynamischer Initialisierung werden nicht notwendigerweise vor der ersten Anweisung in der Hauptfunktion erstellt. Durch Implementierung wird definiert, ob diese Objekte vor der ersten Anweisung in main oder vor der ersten Verwendung einer Funktion oder Variablen erstellt werden, die in derselben Übersetzungseinheit wie die zu initialisierende statische Variable definiert ist. 

In Ihrem Code werden also global_int1 und static_int1 definitiv vor der ersten Anweisung in main initialisiert, da sie statisch initialisiert werden. Global_int2 und static_int2 werden jedoch dynamisch initialisiert, sodass ihre Initialisierung gemäß der oben genannten Regel definiert wird.

Zum zweiten Punkt bin ich mir nicht sicher, was ich meine. Könnten Sie das klarstellen?

1
scl