statische Variable in dll



  • Hallo zusammen,

    erstmal hoffe ich, dass ich im richtigen Forenbereich gelandet bin ­čÖé

    habe ein kleines Problem mit statischen Variablen in einer dll. Einfache Datentypen scheinen zu funktionieren (z.B. Pointer), aber z.b. eine statische map<int, string> funktioniert leider nicht. Beim ersten Aufruf der find Funktion steigt mir das komplette Programm aus.

    An einer Stelle habe ich es so gel├Âst, dass ich dann einfach einen statischen pointer mit new initialisiert habe, nur dann ist er mir wenig sp├Ąter an einer anderen statischen Variable weggekracht. Auch bin ich mir bei Windows nicht so sicher, ob er mir den Speicher nach Programmdurchlauf auch wieder sauber freigibt.

    Auf das Programm habe ich leider keinen Einfluss. Ist ein closed source kommerzielles Programm.

    Ich kompiliere mit dem Intel Composer XE 2011 und Visual Studio 2010.

    Hat jemand eine Idee an was das liegen k├Ânnte? Unter Linux funktioniert das ganze ohne Probleme. Auch wenn nur Funktionen mit nicht statischen Variablen benutzt werden, funktioniert alles.



  • Grunds├Ątzlich geht das schon. Problem kommt vermutlich von der Initialisierungsreihenfolge. Google: static initialization order fiasco .

    windll schrieb:

    An einer Stelle habe ich es so gel├Âst, dass ich dann einfach einen statischen pointer mit new initialisiert habe,

    Besser:

    map<int, string>& getMap()
    {
        static map<int, string> theMap;
        return theMap;
    }
    

    Und dann ├╝berall Zugriff ├╝ber getMap() .

    windll schrieb:

    nur dann ist er mir wenig sp├Ąter an einer anderen statischen Variable weggekracht. Auch bin ich mir bei Windows nicht so sicher, ob er mir den Speicher nach Programmdurchlauf auch wieder sauber freigibt.

    Probier' mal die oben gezeigte Variante. Damit sollte auch der Speicher wieder freigegeben werden. Ansonsten gibt's noch die M├Âglichkeit diverse Initialisierungen/Cleanup in DllMain zu machen.

    ----

    Das ganze ist aber leider ein recht komplexes Problem ohne wirklich gute bzw. universell anwendbare L├Âsung. Falls es nicht klappt hast du aber jetzt ein paar Stichw├Ârter zum Googeln. Bzw. du kannst ja nochmal nachfragen, idealerweise dann mit minimalem Code-Beispiel mit dem das Problem reproduzierbar ist.



  • Hab es mal ausprobiert. Leider exakt das gleiche Verhalten. den print vor dem getMap().find(...) bekomme ich noch, den print danach nicht mehr. Die erste Stelle, die ich durch einen Pointer ersetzt hatte war im Prinzip auch so aufgebaut (Singleton) und ist auch abgest├╝rtzt.

    F├╝r mich sieht das irgendwie so aus, als w├Ąre die Variable ├╝berhaupt nicht initialisiert.



  • Zeig mal den Code.



  • Im Prinzip so, ist nat├╝rlich ne gr├Â├čere Klasse.

    Header

    typedef std::map<std::string, unsigned int> NameMap;
    typedef NameMap::iterator NameMapIt;
    
    class AClass {
    public:
      static NameMap & getNameMap();
      static unsigned int nameToId(const std::string &name);
    };
    

    cpp

    NameMap & AClass::getNameMap() {
      static NameMap nameMap;
      return nameMap;
    }
    
    unsigned int AClass::nameToId(const std::string &name) {
      std::cout << "before find" << std::endl;
      // Programm steigt hier aus.
      NameMapIt found = getNameMap().find(name);
      std::cout << "after find" << std::endl;
    }
    

    Ich habe die getNameMap Methode auch static gemacht, damit ich sie aus einer anderen static Methode aufrufen kann. Das sollte ja aber nichts ausmachen?

    Interessant ist evtl. noch, dass die DLL einen C Einstiegspunkt hat und ich dann ├╝ber ein extern "C" in die C++ Welt gehe.



  • Wer ruft wann/von-wo/wie diese extern "C" Funktion auf?
    Und mit was f├╝r nem Compiler arbeitest du?
    Welche Version der Runtime Library?



  • Also Compiler ist der Intel Composer XE 2011 SP1 mit Visual Studio 2010.

    Es gibt ein paar definierte Einsprungsfunktionen. Diese sind in C geschrieben.

    Aus diesen C Routinen wird z.B. eine Funktion in C++ aufgerufen, welche dann Objekte verwendet.

    c++ Header

    #ifdef __cplusplus
    extern"C" {
    #endif
    
    void myCppFunction(char* name);
    #ifdef __cplusplus
    }
    #endif
    

    c++ .cpp

    void myCppFunction(char* name) {
      // do something
    }
    

    Kompiliert wird mit

    icl /MP /Qstd=c99 /Qvla /O3 /c /nologo /W0 /MD /EHsc /Tc <c files> /Tp <cpp files>
    

    Das Linken selbst wird ├╝ber das Programm gemacht. Zumindest folgende Einstellungen sehe ich.

    /nologo /NOENTRY /INCREMENTAL:NO /subsystem:console /machine:AMD64 /NODEFAULTLIB:LIBC.LIB /NODEFAULTLIB:LIBCMT.LIB /DEFAULTLIB:OLDNAMES.LIB /DEFAULTLIB:LIBIFCOREMD.LIB /DEFAULTLIB:LIBIFPORTMD.LIB /DEFAULTLIB:LIBMMD.LIB /DEFAULTLIB:kernel32.lib /DEFAULTLIB:user32.lib /DEFAULTLIB:advapi32.lib /FIXED:NO /dll /FORCE:UNRESOLVED /MT oldnames.lib user32.lib ws2_32.lib netapi32.lib advapi32.lib
    


  • Probier mal das ganze mit dem Visual Studio Compiler zu bauen.
    Und

    hustbaer schrieb:

    Wer ruft wann/von-wo/wie diese extern "C" Funktion auf?


Log in to reply