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?


Anmelden zum Antworten