Speicherverwaltung unter Windows (Exe mit Dll)



  • Guten Abend !

    Ich bin mir nicht sicher ob der Thread in diesem Forum richtig ist, dennoch erschien es mir am sinnvollsten ...

    Habe eine kleine Frage bezüglich der Speicherverwaltung unter Win32 (speziell XP, aber das dürfte wohl kaum anders sein als Win98-ME evtl. Win2k).

    Mein Hauptprozess (EXE) benötigt eine Dll. Afaik wird diese komplett mit in der Exe "gebündelt" und in den Prozessadressraum gestopft. Unter Win95 hatte damals jeder Prozess 2GB Speicher.

    Nun meine Frage. Es gibt so eine Variablen und Strukturen, die in der Dll als static deklariert sind. Somit sind die doch wärend des gesamten Programmablaufes verfügbar und an ein und der selben Andresse zu finden. -> Das heißt es wird nicht immer eine neue Variable verwendet sondern grobgenommen könnte man sagen, die statische Dll Variable verhält sich so, als hätte ich sie statisch in der Exe deklariert. Richtig ?

    P.S.: Ich hoffe man versteht so halbwegs was ich sagen möchte. Bei Unverständlichkeiten vielleicht eine Rückmeldung. 🙂



  • Wenn du eine Variable erzeugst braucht sie Speicher.
    Da macht es "fast" keine Unterschied ob sie jetzt static ist oder erst erstellt wird

    Du kannst aber unter Windoows angeben das eine DLL erst geladen wird wenn sie gebraucht wird. Das spart Speicher. Dies geht auch mit Staticgeladenen.
    IMHO hängt aber der Speicherverbrauch von den Daten ab die deine Anwendung verwalten muss.



  • Kannst du mal ein Beispiel der Art von static Deklaration zeigen die du meinst?



  • Hallo,

    von deinem Hauptprogramm aus hast du keine Moeglichkeit auf die static-Variable
    zuzugreifen, solange diese nicht exportiert worden ist. Hauptprogramm und DLL
    bekommen jeweils von einander getrennte Speicherbereiche.

    Relativ triviales Beispiel:

    class MyClass
    {
       private:
             static int m_Zaehl;
       public:
             static int GetZaehl()
             { return m_Zaehl; }
             static int SetZaehl(int Zaehl = 0)
             { m_Zaehl = Zaehl; }
    };
    

    Nun erstellst du im Code fuer dein DLL-Projekt irgendwo eine Instanz von
    MyClass und Arbeitest damit:

    //irgendwo im Code fuer die DLL
    MyClass::SetZaehl(5);
    

    Nun willst du die '5' in deinem Hauptprogramm durch folgende Zeile abrufen:

    int Zaehl = MyClass::GetZaehl();
    

    Du wirst dich wundern, aber du wirst mit grosser Wahrscheinlichkeit _keine_
    5 als Ergebnis bekommen. Das liegt daran, dass 'MyClass' im DLL-Projekt
    (hier einfach so vorausgesetzt) nicht exportiert worden ist und somit _nicht_
    als Information in der DLL vorkommt. 'MyClass' wird also rein nur intern im
    DLL-Projekt verwendet und das 'MyClass' welches jetzt hier im Bsp. im Haupt-
    programm genutzt wird, hat rein gar nichts mit dem 'MyClass' der DLL zu tun.

    Hoffe ich konnte das verstaendlich darlegen 😉

    Das es sich um 2 verschiedene Speicherbereiche handelt und man es hier ohne
    Exportierung der Klassen mit verschiedenen Objekten zu tun hat, hab ich auch
    schon ein paar Mal zu spueren bekommen 🙂

    mfg
    v R



  • @all Ohh. Ich bin mir jetzt nicht sicher aber ich glaube das wir uns falsch verstanden haben.

    Ich versuche es noch einmal vielleicht etwas konkreter.

    Ich benutze jetzt das Wort "MEIN" um deutlich zu machen das keine Windows-/Drittanbieterdateien gemeint sind.

    In meiner Exe sind die Dll meiner Dll deklariert und werden ganz normal aufgerufen. Jetzt benötigen einige Dll-Funktionen Strukturen (die gleiche) um Daten verarbeiten zu können. Ich deklariere jetzt aber nur in der Quellcodedatei die Struktur als static und nicht noch in der Exe. Wenn ich jetzt Daten aus der Exe über die Dll-Funktionen in die Struktur einspeise, werden nicht immer eine Struktur angelegt und die alte gelöscht sondern es handelt sich immer um ein und die selbe Struktur während des ganzen Programmablaufes. Ich meine das ich mit dieser Annahme richtig liege.

    Getestet habe ich es in "gewisser" Weise auch schon. Als Exe habe ich einen VB-"Prozess" verwendet, der dann Daten über die Dll-Funktionn(en) in die Struktur einspeist. Zwischendurch habe ich andere Dlls und andere Funktionen der Exe aufgerufen. Danach habe ich mir den Inhalt der Struktur noch einmal komplett anzeigen lassen und siehe da, der Inhalt war unverändert.

    Ich hoffe es ist jetzt etwas deutlicher geworden.

    PAD schrieb:

    Kannst du mal ein Beispiel der Art von static Deklaration zeigen die du meinst?

    Die Struktur ist GLOBAL als static deklariert.

    static struct MyStruct MyGlobalStruct
    


  • Hallo,

    DLL-Intern ist die Struktur die gleiche, da hast du recht. Du kannst lediglich
    nicht vom Hauptprogramm direkt auf diese Zugreifen. Wenn du Funktionen nutzt,
    welche dir die DLL anbietet, ist das natuerlich kein Problem.

    mfg
    v R



  • Gut ! Dann bin ich ja beruhigt. Ich hatte schon gedacht das es zufällig geklappt hat. Also ist das ein ganz normal-gängig-saubere Lösung.



  • Michael__W. schrieb:

    Gut ! Dann bin ich ja beruhigt. Ich hatte schon gedacht das es zufällig geklappt hat. Also ist das ein ganz normal-gängig-saubere Lösung.

    Naja, globale Variablen 😉

    mfg
    v R



  • virtuell Realisticer schrieb:

    Naja, globale Variablen

    Das heißt ???
    Sind die Speicherresistent ?



  • Globale Variablen sind unschoen.

    Allgemein sagt man, so lokal wie moeglich. Andererseits weiss ich ja auch nicht,
    fuer was du diese Struktur benoetigst.

    Es ist nicht im negativen Sinne dir gegenueber gemeint gewesen 🙂

    mfg
    v R



  • virtuell Realisticer schrieb:

    Globale Variablen sind unschoen

    Ästhetischer Code -> Lesbarkeit oder hat das einen anderen Grund.

    Eigentlich verwende ich so gut wie nie globale variablen, doch in diesem Fall, da der Hauptprozess eine EXE in VB geschrieben ist und es dort unter anderem nicht den Datentyp unsigned long gibt (...) musste ich auf diese Variante zurückgreifen.



  • Was für Daten tauscht du mit VB auf diese Art und Weise aus?
    Wie tauschst du die Daten mit VB aus?.

    Falls Strings dabei sind, kann ich im Moment nur warnen, damit kann es Probleme geben. Im Forum gab es auch eine oder zwei threads zu dieser Thematik in den letzten 3 Monaten.

    Das globale Variabeln zu minimieren sind, ist immer richtig. Da su aber diese Variable aus verschiedenen Quellen (VB, C(C++)) bedienen willst und du sie nicht als Passparameter mitgeben kannst, ist das in diesem Falle IMHO die zichtige Lösung.

    👍 Deine Lösung ist wie es auch andere schon bestätigt haben ok.

    ➡ In deinem Fall bedeuted das static bei deiner globalen Variablen das sie außerhalb des C/C++-Files in dem sie deklariert wird nicht sichtbar ist. D.h du kannst sie weder aus einem anderen File dieser DLL noch aus von einem anderen Programm aus ansprechen.

    ➡ Da du die Zugriffsfunktionen in selben File hast, wie diese Globale funktioniert das auch einwandfrei.

    ➡ Wenn du in Zwei Programmen dieselbe dll gleichzeitig nutzt, hast du zwei untersiedliche globale, die nichts voneinander wissen.

    ➡ Falls du von mehreren unterschiedlichen Programmen aus, dieselbe globale nutzen willst, ist dein Verfahren falsch dann braucht du shared memory.

    Ich hoffe ich habe dich nicht verwirrt und viel Spaß



  • Noch als Korrektur:

    IIRC gab es unter Win95 2GB Adreßraum für alle Prozesse. Seit 98 sind das 2GB pro Prozeß, unter NT-basierten Systemen sind auch 3GB möglich.

    globale Variablen:
    Außer daß sie heutzutage das sind was goto in den 80'ern war: so eine art bitterböser Klassenfeind, gibt es effektive Nachteile. Grob kann man sagen: Für EXE ok, für Library meist tabu.

    * Hauptgrund: Multithreading:
    Da alle Threads sich eine Instanz teilen, muß der Zugriff serialisiert werden. Bibliotheken die das nicht tun, können i.a. nicht von mehreren Threads bzw. reentrant aufgerufen werden, und fallen damit häufig aus.

    Die C-Standardbibliotheken, die recht viel mit statischen Buffern oder Variablen arbeiten, verwenden eine Instanz pro Thread. Das can man zwar auf den meisten Systemen auch mit seinen statischen Variablen machen, ist aber nicht portabl. Und die "bequeme" Windows-Lösung ( __declspec(thread) ) funktioniert leider nicht bei dynamisch geladenen DLL's.

    * Global Namespace Pollution
    Der Linker kann globale Symbole mit gleichem Namen nicht trennen, auch wenn sie aus zwei verschiedenen Lib's stammen. Hier helfen aber C++ namespaces.

    * EVENTUELL: Unsauberer Programmierstil
    Die Verwendung vieler globaler Variablen legen den Verdacht auf einen unsauberen Stil nahe. Aber wie so oft sind die globalen Variablen nur ein Indikator und nicht die Ursache. Das eigentliche Problem ist normalerweise ein unsauberer oder zugemüllter Zustandsraum.

    Deswegen kriegt jede MFC-Anwendung von mir sofort ein "extern CXyzApp theApp" verpaßt, ohne das mein Karma leidet. 😉


Anmelden zum Antworten