Initialisierungsreihenfolge von Statics
-
Hi,
mir ist klar, dass die Initialisierungsreihenfolge von mit static deklarierten Variablen über verschiedene Compilation-Units undefiniert ist.
Generell habe ich eine Klasse "Document" von der verschiedene andere Dokumente erben, z.B. XmlDocument, PDFDocument, etc. Etwa so
class Document
{
public:
Deserialize(...);
};class XmlDocument : public Document;
class PDFDocument : public Document;Dann habe ich eine Klasse DocumentCreator (als Singelton!), welche im Prinzip so aussieht
class DocumentCreator : publicSingelton
{
public:
DocumentCreator& Instance();
void Register(std::string& Identification, CreationMethod* Method);
Document* CreateDocument(std::string& Identification);
};In jeder CPP Datei für die verschiedenen Dokumente will ich
DocumentCreator::Instance().Register(std::string("XmlDocument"), &myMethod);
aufrufen. Das passiert ja alles statisch bzw bei der Initialisierung. Wenn ich also ein neues Dokument hinzufügen möchte, brauche ich lediglich die CPP Datei zum Projekt hinzulinken und beim ausführen des Startup-Code führt der Compiler automatisch das Registerieren der Klasse beim DocumentCreator aus.
Das Problem ist jetzt, dass ich natürlich sichergehen muss, dass mein Singelton BEVOR allem anderen initialisiert wird. (Innerhalb der CPP Datei fürs Singelton befindet sich die Instanzvariable des Singeltons, welche dort zunächst auf 0 gesetzt wird. Nach Singelton-Manir wird in Instance() geprüft ob diese Variable noch 0 ist und dann eben ggf. eine Instanz erzeugt - ich will sichergehen, dass diese Variable BEVOR dem ersten Aufruf zum Singelton auf 0 initialisiert wurde)
Kennt jemand einen Ausweg dem dem Dilemma? Da ja die Initialisierungsreihenfolge von statics undefiniert ist, bin ich nicht sicher, ob man das überhaupt irgendwie auf die Weise, wie ich sie bisher habe, lösen kann.
-
Was soll das für einen Sinn machen? - Du weisst ja, dass du sobald du
::Instanceaufrufst das Objekt falls es noch nicht existiert hat erstellt wird. Probleme kann das eigentlich nur geben, wenn du noch andere Singletons hast und die miteinander reden sollen und sich irgendwie zyklisch aufrufen. Das wäre aber sonst ein genereller Denkfehler und das hast du hier ja auch nicht, wenn ich das richtig sehe..Im übrigen ist ist es garantiert, dass statische Variablen vor der main initialisiert sind.
-
Morle schrieb:
ich will sichergehen, dass diese Variable BEVOR dem ersten Aufruf zum Singelton auf 0 initialisiert wurde)
Das war glaube ich bei globalen integers garantiert.
http://www.tilander.org/aurora/2007/10/static-initialization-in-c.html
-
volkard schrieb:
Morle schrieb:
ich will sichergehen, dass diese Variable BEVOR dem ersten Aufruf zum Singelton auf 0 initialisiert wurde)
Das war glaube ich bei globalen integers garantiert.
http://www.tilander.org/aurora/2007/10/static-initialization-in-c.htmlDanke. Das beantwortet meine Frage. Dort steht sinngemäß das alle Variablen initialisiert werden bevor irgendwelche Funktionen aufgerufen werden. Da ich ja eine Funktion aufrufe, ist also die Singeltonvariable vorher mit 0 initialisiert worden.
-
drakon schrieb:
Im übrigen ist ist es garantiert, dass statische Variablen vor der main initialisiert sind.
Das ist ja das Problem. Es war die Frage in welcher Reihenfolge das geschieht, da ich ja noch bevor die Main überhaupt ausgeführt wird schon ::Instance aufrufen will.
-
Edit: war für dein Problem eher ungeeignet.
-
Morle schrieb:
volkard schrieb:
Morle schrieb:
ich will sichergehen, dass diese Variable BEVOR dem ersten Aufruf zum Singelton auf 0 initialisiert wurde)
Das war glaube ich bei globalen integers garantiert.
http://www.tilander.org/aurora/2007/10/static-initialization-in-c.htmlDanke. Das beantwortet meine Frage. Dort steht sinngemäß das alle Variablen initialisiert werden bevor irgendwelche Funktionen aufgerufen werden. Da ich ja eine Funktion aufrufe, ist also die Singeltonvariable vorher mit 0 initialisiert worden.
häh...
Ich glaub ich bin blind...
Wo steht "das(s) alle Variablen initialisiert werden bevor irgendwelche Funktionen aufgerufen werden."?
-
Objects with static storage duration are required by the language to be first zero/constant initialized before anything else happens.
Du meinst sicherlich diese Passage, aber zero/constant initialized ist doch nicht gleichzusetzen mit initialisiert, oder?
Wenn ich einen Speicherbereich habe, wo ein statisches Objekt rein soll und
es sind erstmal nur 0en drin, dann ist mein Object doch nicht initialisiert?
Für deinen Fall ist das evtl. ausreichend, aber die Verallgemeinerung scheint mir falsch
-
Newbie19 schrieb:
Objects with static storage duration are required by the language to be first zero/constant initialized before anything else happens.
Du meinst sicherlich diese Passage, aber zero/constant initialized ist doch nicht gleichzusetzen mit initialisiert, oder?
In dem Fall aber ausreichend. Also wenn man Integers, Zeiger etc. auf 0 oder einen compile-time konstanten Ausrduck initialisiert braucht, geht das wunderbar.
Und garantierterweise bevor irgendwelche Funktionen aufgerufen werden.
-
Newbie19 schrieb:
häh...
Ich glaub ich bin blind...
Wo steht "das(s) alle Variablen initialisiert werden bevor irgendwelche Funktionen aufgerufen werden."?Nirgends.
Es geht nur um sowas wie zum Beispiel einen globalen int. Den kannste supi als Flag nehmen, zum Beispiel mit dem alten cout-initialiszer.
Natürlich geht es nicht um Variablen, die Klassenobjekte sind und per Konstruktoraufruf initialisiert werden.
-
Danke euch beiden für die Bestätigung!!!
Das mit der 0-Initialisierung ist keine Neuigkeit für mich, ansonsten
hätte man z.B. (teilweise) Probleme mit boost::call_onceDass diese Garantie in seinem Fall ausreicht, sehe ich ein, ich war nur durch
die Verallgemeinerung iritiert.