[autorun vor main] segmentation fault
-
Folgender Code bereitet mir Kopfweh.. Vermutlich mach ich wieder was nicht standardmäßiges... ACHTUNG: das Snippet sieht in Wirklichkeit etwas anders aus... aber ich wollte das wesentliche zeigen. Ziel ist es, dass sich diverse Singeltons VOR main bei einer Art Factory registrieren.
//header base.h class Base { public: std::string getTypeId()=0; static void registerDerivedInstance(Base* inst) { myMap.insert(std::pair<std::string, Base*>(inst->getTypeID(), inst)); } private: static std::map<std::string, Base*> myMap; }; //base.cpp #include "./base.h" std::map<std::string, Base*> Base::myMap; //header derived.h #include "base.h" class Derived : public Base { public: static Derived* getInstance() { static Derived instance; return &instance; } private: Derived ( const Derived& ); //no copy allowed Derived () : Base() {} public: std::string getTypeID() { return "MySignature"; } }; //main.cpp #include "base.h" #include "derived.h" bool test = (Base::registerDerivedInstance(Derived::getInstance()), true ); int main() { Base::registerDerivedInstance(Derived::getInstance()); return 0; }Unter Windows MSVC8.0 läuft das problemlos. Unter Linux gcc3.4.4 bekomme ich bei Programmstart einen segmentation fault.
Und zwar bei myMap.insert(std::pair<std::string, Base*>(inst->getTypeID(), inst));
ersetze ich das durch std::cout<<myMap.size()<<std::endl; geht es auch. ICh habe dann folgendes ausprobiert:void WbWriter::registerWriterInstance(Base* nnn) { static bool hack = true; if(hack) { std::map<std::string, Base*> test; test.insert(std::pair<std::string, Base*>(nnn->getTypeID(), nnn)); myMap= test; std::cout<<WbWriter::myMap.size()<<" "<<nnn->getTypeID()<<std::endl; hack = false; } else myMap.insert(std::pair<std::string, Base*>(nnn->getTypeID(), writer)); }dann erhalte ich "1", "1"
Weiß jemand wo das Problem liegt? An der statischen map? Kann ich nicht immer drauf zugreifen? Die ist doch zu Programmstart schon verfügbar oder nicht?
Meine ganzen anderen Factories funktionen so einwandfrei. Hie rist es eine Spiezialversion, da e ssich um Singeltons handelt...
-
okay. Mittlerweile habe ich noch einges ausprobiert.
ich habe z.B. einen statischen Pointer auf die map verwendet.
Diesen habe ich in der cpp mit new initilaisiert. ein std::cout der Adresse m Konstrukttor zeigt mit jedoch bei Ausführung "VOR" main als Adresse NULL an. Derselbe Aufruf in main liefert jedoch die Adresse auf eine gültige Instanz. Daher vermute ich, dass bei Aufruf der Methode VOR main einfach nicht gewährleistet ist, dass das statische Element (sei es Pointer auf ne map oder nur eine map) bereits instantiiert ist.
Daher werde ich jetzt wie bei den anderen Klassen auch, einfach eine DerivedSingletonFactory erstellen.
-
Das ist das Problem mit den statischen (globalen) Variablen: man weiß nie, in welcher Reihenfolge sie erzeugt werden (meistens kann man es über die Reihenfolge der Übersetzungseinheiten kontrollieren - aber das ist keine Garantie).
Ob nunstd::map<std::string, Base*> Base::myMap;oder zuerst
bool test = (Base::registerDerivedInstance(Derived::getInstance()), true );welche ja die map benutzt, instanziiert wird, ist eben nicht festgelegt!!!
Erzeuge dir aus der Map selbst ein Singleton (mit Hilfe einer statischen Funktion), dann bist du auf der sicheren Seite.
-
okay. genau wie ich letztlich vermuted habe. mittlerweile habe ich aus der map ein singleton gemacht und es läuft wunderbar. danke