Frage

Ich war über SIOF aus einem Buch zu lesen und es gab ein Beispiel:

//file1.cpp
extern int y;
int x=y+1;

//file2.cpp
extern int x;
int y=x+1;  

Jetzt meine Frage:
In obigem Code werden folgende Dinge passieren?

  1. während file1.cpp Kompilieren Compiler Blätter y, wie es ist d.h keine Zuteilung von Speicher für sie.
  2. Compiler ordnet Speicher für x, sie aber nicht initialisiert werden.
  3. Während file2.cpp Kompilieren Compiler Blätter x, wie es ist nicht das heißt Speicher für sie nicht zuordnen.
  4. Compiler ordnet Speicher für y, sie aber nicht initialisiert werden.
  5. Während die Verknüpfung file1.o und file2.o, lassen Sie jetzt file2.o zuerst initialisiert wird, so jetzt:
    Does x bekommt Anfangswert von 0? oder nicht initialisiert nicht erhalten?
War es hilfreich?

Lösung

Die Initialisierungsschritte werden in 3.6.2 „Initialisierung nicht lokale Objekte“ der C ++ Standard gegeben:

Schritt 1: x und y Null initialisiert, bevor eine andere Initialisierung stattfindet.

Schritt 2: x oder y dynamisch initialisiert - die man durch den Standard nicht spezifiziert ist. Diese Variable wird den Wert 1 erhalten, da die andere Variable Null initialisiert wurden, werden.

Schritt 3:. Die anderen Variablen dynamisch initialisiert werden, um den Wert 2 bekommen

Andere Tipps

SIOF ist sehr viel ein Runtime-Artefakt, der Compiler und Linker haben nicht viel mit ihm zu tun. Betrachten wir die atexit () Funktion, es Funktionen Register beim Beenden des Programms aufgerufen werden. Viele CRT-Implementierungen etwas ähnliches für Programminitialisierung haben, nennen wir es atinit ().

initialisieren diese globalen Variablen erfordert die Ausführung von Code, kann der Wert nicht vom Compiler bestimmt werden. So erzeugt der Compiler-Schnipsel von Maschinencode, der die Expression und weist den Wert auszuführen. Diese Schnipsel müssen vor main () Lauf ausgeführt werden.

Das ist, wo atinit () ins Spiel kommt. Eine gemeinsame CRT Implementierung geht eine Liste von atinit Funktionszeiger und die Initialisierung Schnipsel, um auszuführen. Das Problem ist die Reihenfolge, in der die Funktionen registriert sind, in der atinit () Liste. Während atexit () eine gut definierte LIFO Ordnung hat, und durch die Reihenfolge implizit bestimmt wird, in dem der Code aufruft atexit (), ist dies nicht der Fall für atinit Funktionen. Die Sprachspezifikation erfordert keine Ordnung, gibt es nichts, was Sie in Ihrem Code tun könnten, einen Auftrag zu geben. SIOF ist das Ergebnis.

Eine mögliche Implementierung ist die Compiler Funktionszeiger in einem separaten Abschnitt emittiert. Der Linker fügt sie zusammen, die atinit Liste zu erzeugen. Wenn Ihr Compiler tut, dann wird die Initialisierungsreihenfolge durch die Reihenfolge bestimmt, in dem Sie die Objektdateien verknüpfen. Schauen Sie sich die Map-Datei, sollten Sie den atinit Abschnitt sehen, ob Ihr Compiler dies tut. Es wird nicht atinit heißen, sondern eine Art von Namen mit „init“ ist wahrscheinlich. einen Blick auf dem CRT-Quellcode nehmen, die Haupt () aufruft, sollte Einsicht auch geben.

Der ganze Sinn (und der Grund, warum es ein „Fiasko“ genannt) ist, dass es unmöglich ist, mit Sicherheit zu sagen, was in einem Fall wie dies geschehen wird. Im Wesentlichen sind Sie nach etwas fragen unmöglich (die zwei Variablen um eins größer als die anderen jeweils sein). Da sie das nicht tun können, ist zu einem gewissen Frage offen, was sie tun - sie 0/1 produzieren könnten, oder 1/0 oder 1/2 oder 2/1 oder möglicherweise (best case) nur ein Fehler Nachricht.

Es ist Compiler abhängig und kann Laufzeit abhängig. Ein Compiler kann lazily initialize statische Variablen entscheiden, wann die erste Variable in einer Datei zugegriffen wird, oder als jede Variable zugegriffen wird. Sonst wird es alle statischen Variablen, die von Datei zur Startzeit initialisieren, mit der Bestellung auf den Link Reihenfolge der Dateien in der Regel abhängig. Die Datei, um auf Abhängigkeiten oder andere, Compiler abhängig Einflüssen basierend verändern könnte.

sind statische Variablen in die Regel auf Null initialisiert, wenn sie einen konstanten initializer haben. Auch dies ist Compiler abhängig. So eine dieser Variablen wahrscheinlich Null sein wird, wenn die andere initialisiert wird. Da jedoch beide initializers haben einige Compiler können die Werte undefiniert lassen.

Ich denke, das wahrscheinlichste Szenario wäre:

  1. Der Raum wird für die Variablen zugewiesen, und beide haben den Wert 0.
  2. Eine Variable, sagen wir x, initialisiert und auf den Wert 1.
  3. Die andere, sagen wir y, initialisiert und auf den Wert 2.

Sie können führen Sie es immer und sehen. Es könnte sein, dass einige Compiler Code generieren würde, die in eine Endlosschleife geht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top