Wann ordnen globale Variablen ihren Speicher zu?

8

Es hat mich eine Weile gestört, aber ich habe in dieser Angelegenheit keine gute Quelle gefunden. Ich habe einige globale Variablen in meinem Code. Es ist offensichtlich, dass sie in einer bestimmten Reihenfolge initialisiert werden, aber ist das Speicher für all diese Objekte reserviert, bevor eine Initialisierung stattfindet?

Hier ist das einfache Beispiel, was in meinem Code schief gehen könnte und wie ich die Antwort verwenden könnte:

Ich hatte ein map<RTTI, object*> objectPool , das Beispiele jeder Klasse in meinem Code enthält, mit dem ich Objekte aus einer Datei geladen habe. Um diese Beispiele zu erstellen, verwende ich einige globale Variablen, um Klasseninstanzen in objectPool einzuführen. Aber manchmal wurden diese Beispielinstanzen vor dem ObjectPool selbst initialisiert. Und das erzeugte Laufzeitfehler.

Um diesen Fehler zu beheben, habe ich einen verzögerten Initialisierer map<RTTI,object*>* lateInitializedObjectPool; verwendet. Nun prüft jede Instanz zunächst, ob der objectPool initialisiert ist, initialisiert sie falls nicht und stellt sich dann selbst in den Objektpool ein. Es scheint gut zu funktionieren, aber ich mache mir Sorgen, wenn auch das für den Objektpoolzeiger benötigte Speicher nicht reserviert wird, bevor andere Klassen sich selbst vorstellen und das eine Zugriffsverletzung verursachen kann.

    
Ali1S232 28.06.2011, 09:50
quelle

3 Antworten

6

Variablen, die im Namespacebereich (im Gegensatz zu Klassen oder Funktionen) deklariert sind, haben den Platz für die Objekte selbst (sizeof (ObjectType)), die vom ausführbaren (oder DLL-) Loader zugewiesen werden. Wenn das Objekt ein POD ist, das Aggregat-Initialisierung verwendet, werden seine Werte normalerweise dadurch festgelegt, dass der Linker diese Werte direkt in die ausführbare Datei schreibt und der Loader der EXE diese einfach in den Speicher sendet. Bei Objekten, die keine Aggregat-Initialisierung verwenden, werden ihre Werte anfänglich auf Null gesetzt.

Wenn eines dieser Objekte Konstruktoren hat, werden diese Konstruktoren ausgeführt, bevor main ausgeführt wird. Wenn also einer dieser Konstruktoren Speicher dynamisch zuweist, dann tun sie dies. Nachdem die ausführbare Datei geladen wurde, aber bevor main ausgeführt wurde.

    
Nicol Bolas 28.06.2011, 10:05
quelle
3

Normalerweise gibt es getrennte Speicherbereiche für Variablen, die der Compiler:

  • hat zuerst alle 0s ausgearbeitet - vielleicht mit einem Pre- main() -Konstruktor, der ausgeführt wird, um seinen Inhalt zu ändern
  • prededed haben einen spezifischen Wert ungleich 0, so dass sie in einer vorkonstruierten Form in das ausführbare Bild geschrieben werden können und die Seite einsatzbereit ist.

Wenn ich einen "separaten Speicherbereich" sage, meine ich etwas Speicher, den der ausführbare OS-Lader für den Prozess arrangiert, genauso wie für den Stapel oder den Heap, aber unterschiedlich, da diese Bereiche eine fest vorgegebene Größe haben. In UNIX ist der oben erwähnte Speicherbereich für alle 0 im Allgemeinen als "BSS" bekannt, der nicht mit 0 initialisierte Bereich als "Daten" - siehe Ссылка für Details.

    
Tony Delroy 28.06.2011 10:05
quelle
1

C ++ hat den Begriff "statische Speicherdauer". Dies bezieht sich auf alle Arten von Variablen, die während der Ausführung eines Programms einen festen Platz einnehmen. Dazu gehören nicht nur globale Variablen, sondern auch static Variablen auf Namensraum-, Klassen- und Funktionsebene.

Beachten Sie, dass die Speicherzuweisung in allen Fällen vor main erfolgen kann, die tatsächliche Initialisierung jedoch unterschiedlich ist. Außerdem werden einige von ihnen initialisiert, bevor sie normal initialisiert werden. Genau wie dies geschieht, ist nicht spezifiziert: Der Compiler kann einen versteckten Funktionsaufruf hinzufügen, oder das OS passiert nur zufällig den Prozessraum, etc.

    
MSalters 28.06.2011 11:42
quelle

Tags und Links