Ist es sicher, Vektoren während der statischen Initialisierung zu erstellen und zu verwenden?

8

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:

  1. Was ist das "statische Initialisierungsreihenfolge-Fiasko"?

    Es wird in C ++ - FAQ 10.14

    erklärt
  2. Warum 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.

  3. Wie sieht dieser Code eigentlich aus?

    %Vor%
aecolley 16.06.2014, 23:46
quelle

2 Antworten

4

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 () auf ein solches Problem stoßen könnten:

  

[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ßlich this .

     

[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.

    
quelle
2

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.

    
Tony Delroy 16.06.2014 23:51
quelle