Ich habe C ++ - Code, der Variablen für statische Lebenszeit deklariert, die durch Funktionsaufrufe initialisiert werden. Die aufgerufene Funktion erstellt eine vector
-Instanz und ruft ihre push_back
-Methode auf. Verletzt der Code das Doom über das statische Cias-Initialisierungsreihenfolge-Fiasko? Wenn nicht, warum nicht?
Zusätzliche Informationen:
Was ist das "statische Initialisierungsreihenfolge-Fiasko"?
Es wird in C ++ - FAQ 10.14
erklärtWarum sollte ich denken, dass die Verwendung des Vektors das Fiasko auslösen könnte?
Es ist möglich, dass der vector
-Konstruktor den Wert einer anderen Variablen für die statische Lebensdauer verwendet, die dynamisch initialisiert wird. Wenn ja, dann gibt es nichts, was sicherstellen würde, dass die Variable vector
initialisiert wird, bevor ich vector
in meinem Code verwende. Das Initialisieren von result
(siehe Code unten) könnte den vector
-Konstruktor aufrufen, bevor vector
die Abhängigkeiten vollständig initialisiert und Zugriff auf nicht initialisierten Speicher ermöglicht.
Wie sieht dieser Code eigentlich aus?
%Vor% Glücklicherweise werden static
-Objekte bereits vor der beliebigen anderen Initialisierung auf Null initialisiert (sogar vor der "echten" Initialisierung derselben Objekte), so dass Sie wissen, dass NULL
dies tut lange bevor Register
zuerst aufgerufen wird. 1
Nun, in Bezug auf die Arbeit mit Ihrem Vektor scheint es, dass Sie (
[C++11: 17.6.5.9/3]:
Eine C ++ - Standardbibliotheksfunktion darf Objekte (1.10), auf die andere Threads als der aktuelle Thread zugreifen können, nicht direkt oder indirekt ändern, es sei denn, auf die Objekte wird direkt oder indirekt über die nichtkonstanten Argumente der Funktion zugegriffen, einschließlichthis
.
[C++11: 17.6.5.9/4]:
[Anmerkung: Dies bedeutet beispielsweise, dass Implementierungen ein statisches Objekt nicht ohne Synchronisation für interne Zwecke verwenden können, da dies auch in nicht explizit genannten Programmen zu einem Datenrennen führen kann Objekte zwischen Threads teilen. -Endnote]
Beachten Sie, dass, obwohl in dieser Anmerkung eine Synchronisierung erforderlich ist, dies in einer Passage erwähnt wurde, die letztendlich bestätigt, dass static
Implementierungsdetails ansonsten erlaubt sind.
Vor diesem Hintergrund scheint es, als sollte der Standard weiterhin angeben, dass der Benutzercode den Betrieb auf Standardcontainern während der statischen Initialisierung vermeiden sollte, wenn die Absicht bestand, dass die Semantik eines solchen Codes nicht garantiert werden konnte; Ich würde dies als einen Fehler im Standard betrachten, so oder so. Es sollte klarer sein.
1 Und es ist ein NULL-Zeiger, egal was Bit-weise Darstellung dieser kann sein, anstatt ein Blot auf alle Null-Bits.
vector
hängt nicht von irgendetwas ab, das seine Verwendung bei der dynamischen Initialisierung von Statiken verhindert. Das einzige Problem mit Ihrem Code ist ein Mangel an Thread-Sicherheit - kein besonderer Grund zu denken, dass Sie sich darum kümmern sollten, es sei denn, Sie haben Statik, deren Konstruktion Threads hervorbringt ....
Das Initialisieren von
result
(siehe Code unten) könnte den Vektorkonstruktor aufrufen, bevor diese Klasse vollständig initialisiert wird, was zum Zugriff auf nicht initialisierten Speicher führt.
Nein ... Initialisierung von result
Aufrufe AddQuery
welche prüft if (pending == NULL)
- Die Initialisierung auf NULL
wurde sicherlich vor jeder dynamischen Initialisierung durchgeführt, pro 3.6.2 / 2:
Konstante Initialisierung wird durchgeführt:
...
- if ein Objekt mit statischer oder Thread Speicherdauer wird nicht durch einen Konstruktoraufruf initialisiert, und wenn entweder das Objekt value-initialisiert oder ist, ist jeder vollständige Ausdruck, der in seinem Initialisierer erscheint, ein konstanter Ausdruck
Auch wenn die result
Zuweisung in einer anderen Übersetzungseinheit ist, ist es sicher. Siehe 3.6.2 / 2:
Die Nullinitialisierung und die Konstanteninitialisierung werden zusammen statische Initialisierung genannt; Alle anderen Initialisierungen sind dynamische Initialisierung . Die statische Initialisierung sollte vor jeder dynamischen Initialisierung durchgeführt werden.
Tags und Links c++ stdvector static-initialization