Dll Speicherverwaltung

8

Ich habe wenig Zweifel daran, wie Windows den Speicher einer .dll verwaltet.

  • wenn .dlls in den Host geladen werden Prozess, wie wird der Speicher verwaltet?

  • Erlangt .dll Zugriff auf das gesamte Verzeichnis Speicher verfügbar für den Host-Prozess oder nur ein Teil davon? d. h da ist eine Beschränkung, wenn Speicher ist zugewiesen von einer Funktion innerhalb der .dll?

  • Werden STL-Klassen wie string, vector (dynamisch zunehmender Speicher) usw., die von der dll, arbeite ohne Problem hier?

SysAdmin 27.10.2010, 08:33
quelle

2 Antworten

4

"Speicherverwaltung" ist typischerweise eine getrennte Zuständigkeit. Das Betriebssystem übergibt den Platz in großen Blöcken an die Laufzeit, die sie dann in kleineren Bits an das Programm verteilt. Dieser Adreßraum kann RAM zugewiesen haben oder nicht. (Wenn nicht, gibt es Swap-Speicherplatz, um es zu unterstützen)

Wenn eine DLL geladen wird, weist Windows Adressraum für die Code- und Datensegmente zu und ruft DllMain() auf. Der C ++ - Compiler hat angeordnet, globale Ctors von DllMain() aufzurufen. Wenn die DLL in C ++ geschrieben ist, hängt sie wahrscheinlich von einer C ++ - Laufzeit-DLL ab, die wiederum von Kernel32.DLL und User32.DLL abhängt. Windows versteht solche Abhängigkeiten und sorgt dafür, dass sie in der richtigen Reihenfolge geladen werden.

Es gibt nur einen Adressraum für eine Prüfung, so dass eine DLL Zugriff auf den gesamten Speicher des Prozesses bekommt. Wenn eine DLL in zwei Prozessen geladen wird, gibt es zwei logische Kopien des Codes und der Daten. (Kopien des Codes und schreibgeschützte Daten können jedoch denselben physischen RAM verwenden).

Wenn die DLL Speicher mit Betriebssystemfunktionen zuweist, weist Windows den Speicher dem Prozess zu, von dem die DLL diese Zuweisung vorgenommen hat. Der Prozess muss den Speicher zurückgeben, jedoch kann dabei auch jeder Code im Prozess verwendet werden. Wenn Ihre DLL Speicher mit C ++ - Funktionen zuweist, wird dies durch Aufruf von operator new in der C ++ - Laufzeit-DLL getan. Dieser Speicher muss zurückgegeben werden, indem operator delete in der (gleichen) C ++ - Laufzeit-DLL aufgerufen wird. Auch hier spielt es keine Rolle, wer das macht.

STL-Klassen wie vector<> können mehrfach instanziiert werden, aber es spielt keine Rolle, solange Sie den gleichen Compiler verwenden. Alle Instanziierungen sind im Wesentlichen gleich, und alle werden den Speicher des Vektors an die gleiche Zuordnungsfunktion zurückgeben.

Es gibt zwei Hauptannahmen in dieser Erklärung:

  1. Die EXE und ihre DLLs sind alle mit dem gleichen Compiler
  2. kompiliert
  3. Die EXE und ihre DLLs sind alle mit der C ++ - Laufzeit-DLL verknüpft (d. h. nicht statisch verknüpft)

Die statische Verknüpfung mit der C ++ - Laufzeit ist nützlich, wenn Sie eine einzelne, eigenständige EXE-Datei senden möchten. Aber wenn Sie bereits DLLs versenden, sollten Sie die C ++ - Laufzeit auch in einer eigenen DLL behalten.

    
MSalters 27.10.2010, 11:04
quelle
3
  

Er erhält .dll Zugriff auf das gesamte   Speicher verfügbar für den Host-Prozess   oder nur ein Teil davon? d. h. ist da   eine Einschränkung, wenn Speicher zugewiesen wird   durch eine Funktion innerhalb der .dll?

Nachdem eine DLL in den Hostprozess geladen wurde, gibt es keinerlei Unterscheidung für code "living" in der DLL vs. code "living" im ursprünglichen ausführbaren Modul. Für den ausgeführten Prozess sind alle Speicherbereiche gleich, unabhängig davon, ob sie von einer DLL oder von der ursprünglichen ausführbaren Datei stammen.

Es gibt keine Unterschiede, was der Code aus der DLL tun kann und was der Code, der im ursprünglichen Exec-Modul kompiliert wurde, tun kann.

Das heißt, sind Unterschiede bei der Verwendung des Heapspeichers - diese werden in den Fragen erklärt Space_C0wb0y lieferte die Links für die Kommentare

  

Werden STL-Klassen wie string, vector   (dynamisch wachsender Speicher) usw   verwendet von der DLL, Arbeit ohne Problem   hier?

Sie werden Probleme erstellen (lösbar, aber immer noch), wenn Sie sie in der Schnittstelle Ihrer DLL verwenden. wird (oder sollte nur in sehr seltenen Fällen) Probleme verursachen, wenn Sie sie nicht auf der DLL-Schnittstellenebene verwenden. Ich bin mir sicher, dass es dafür ein paar spezifischere Fragen und Antworten gibt.

Grundsätzlich, wenn Sie sie auf der Interface-Ebene verwenden, müssen die DLL und die EXE mit "genau" denselben Flags kompiliert werden, d. h. die Typen müssen binärkompatibel sein. I.e. Wenn die Flags (Optimierung, usw.) in Ihrer DLL sich von denen in der EXE unterscheiden, so dass ein std::string im EXE anders als die DLL im Speicher unterschiedlich angeordnet ist, dann wird ein String-Objekt zwischen den beiden übergeben in einem Crash oder stumme Fehler (oder Dämonen fliegen aus der Nase).

Wenn Sie die STL-Typen nur innerhalb von Funktionen oder zwischen Funktionen innerhalb Ihrer DLL verwenden, spielt deren Kompatibilität mit der EXE keine Rolle.

    
Martin Ba 27.10.2010 11:02
quelle

Tags und Links