Nehmen wir an, ich schreibe eine DLL in C++ und deklariere ein globales Objekt einer Klasse mit einem nicht-trivialen Destruktor. Wird der Destruktor beim Entladen der DLL aufgerufen?Was passiert mit globalen Variablen, die in einer DLL deklariert sind?
Antwort
In einer Windows C++ - DLL werden alle globalen Objekte (einschließlich statischer Member von Klassen) kurz vor dem Aufruf von DllMain mit DLL_PROCESS_ATTACH erstellt, und sie werden direkt nach dem Aufruf von DllMain mit DLL_PROCESS_DETACH zerstört.
Jetzt, müssen Sie drei Probleme berücksichtigen:
0 - Natürlich globale Nicht-const Objekte sind böse (aber Sie wissen bereits, dass, also werde ich mentionning Multithreading, Schlösser, Gott-Objekte vermeiden, usw. .)
1 - Die Reihenfolge der Konstruktion von Objekten oder verschiedenen Kompilierungseinheiten (dh CPP-Dateien) ist nicht garantiert, so dass Sie nicht hoffen können, dass das Objekt A vor B erstellt wird, wenn die zwei Objekte in zwei verschiedenen Instanzen vorliegen CPPs. Dies ist wichtig, wenn B von A abhängt. Die Lösung besteht darin, alle globalen Objekte in derselben CPP-Datei zu verschieben, da innerhalb derselben Kompilierungseinheit die Reihenfolge der Instanziierung der Objekte die Reihenfolge der Konstruktion (und die Umkehrung der Reihenfolge) ist der Zerstörung)
2 - Es gibt Dinge, die in der DllMain verboten sind. Diese Dinge sind wahrscheinlich auch in den Konstrukteuren verboten. Also vermeide es, etwas zu sperren. Siehe Raymond Chen ausgezeichneten Blog zum Thema:
http://blogs.msdn.com/oldnewthing/archive/2004/01/27/63401.aspx
http://blogs.msdn.com/oldnewthing/archive/2004/01/28/63880.aspx
In diesem Fall faul Initialisierung interessant sein könnte: Die Klassen bleiben in einem "nicht initialisierten" Zustand (interne Zeiger sind NULL, Booleans sind falsch, was auch immer), bis Sie eine ihrer Methoden aufrufen, an denen sie sich initialisieren. Wenn Sie diese Objekte innerhalb der Hauptfunktion (oder einer der Hauptfunktionen des Hauptprogramms) verwenden, sind Sie in Ordnung, da sie nach der Ausführung von DllMain aufgerufen werden.
3 - Natürlich, wenn einige globale Objekte in DLL A von globalen Objekten in DLL B abhängen, sollten Sie sehr sehr vorsichtig mit der DLL-Ladereihenfolge und damit Abhängigkeiten sein.In diesem Fall werden DLLs mit direkten oder indirekten zirkulären Abhängigkeiten Ihnen eine wahnsinnige Menge an Kopfschmerzen verursachen. Die beste Lösung besteht darin, die zirkulären Abhängigkeiten zu durchbrechen.
P.S .: Beachten Sie, dass Konstruktor in C++ werfen kann und Sie keine Ausnahme mitten in einem DLL-Laden möchten, also stellen Sie sicher, dass Ihre globalen Objekte keine Ausnahme ohne einen sehr guten Grund verwenden. Da korrekt geschriebene Destruktoren nicht zum Werfen berechtigt sind, sollte die DLL-Entladung in diesem Fall in Ordnung sein.
Es sollte aufgerufen werden, wenn entweder die Anwendung beendet oder die DLL entladen wird, je nachdem, was zuerst eintritt. Beachten Sie, dass dies etwas von der tatsächlichen Laufzeit abhängig ist, für die Sie kompilieren.
Achten Sie auch auf nicht-triviale Destruktoren, da sowohl Timing- als auch Bestellprobleme auftreten. Ihre DLL wird möglicherweise entladen nach eine DLL, auf die Ihr Destruktor angewiesen ist, die offensichtlich Probleme verursachen würde.
Wenn DllMain mit FdwReason = DLL_PROCESS_DETACH Parameter aufgerufen wird, bedeutet dies, dass die DLL von der Anwendung entladen wird. Dies ist die Zeit bevor der Destruktor globaler/statischer Objekte aufgerufen wird.
Diese Seite von Microsoft geht in die Details der DLL-Initialisierung und Zerstörung von Globals:
http://msdn.microsoft.com/en-us/library/988ye33t.aspx
Wenn Sie den eigentlichen Code sehen möchten, die ausgeführt wird, wenn eine DLL-Verknüpfung, bei %ProgramFiles%\Visual Studio 8\vc\crt\src\dllcrt0.c
einen Blick darauf werfen.
Von der Inspektion werden Destruktoren über _cexit()
aufgerufen, wenn der interne Referenzzähler, der von der DLL-CRT gehalten wird, Null erreicht.
In Windows binäre Bilddateien mit der Erweiterung * .exe, * .dll sind in PE format Solche Dateien haben Einstiegspunkt. Sie können es mit dumpbin Tool wie
dumpbin anzuzeigen/headers
dllname.dll Wenn Sie C-Laufzeit von Microsoft verwenden, dann wird Ihr Einstiegspunkt wird so etwas wie * CRTStartup oder * DllMainCRTStartup
Solche Funktionen erfüllen Initialisierung von C und C++ Laufzeit und delegieren Ausführung (Haupt, WinMain) oder DllMain ist.
Wenn Sie Microsofts VC-Compiler, dann können Sie auf Quelltext dieser Funktionen in Ihr VC-Verzeichnis sehen:
- crt0.c
- dllcrt0.c
DllMainCRTStartup Prozess alle Dinge Sie müssen Ihre globalen Variablen von .data-Abschnitten im normalen Szenario initialisieren/detinieren, wenn sie die Benachrichtigung DLL_PROCESS_DETACH während des Dll-Entladens abrufen. Zum Beispiel:
- Haupt- oder WinMain von Start Faden Programm kehrt Steuerfluss
- Sie explictly Free aufrufen und verwenden-dll-Zähler Null
- 1. Exportieren von globalen Variablen aus DLL
- 2. Ausgabe mit einer globalen Variablen
- 3. Problem mit globalen Variablen
- 4. Problem mit einer globalen Variablen in PHP
- 5. Welche globalen globalen Variablen müssen für ein Python-Modul deklariert werden?
- 6. Was ist der Gültigkeitsbereich von Variablen, die in einem statischen Block in Java deklariert sind?
- 7. Speicher Datenbankverbindung in einer globalen Variablen
- 8. Verwenden einer globalen Variablen in Javascript
- 9. Was ist der idiomatische Weg, um Variablen zu behandeln, die in mehreren for-Schleifen deklariert sind?
- 10. Warum löst Strcpy einen Segmentierungsfehler mit globalen Variablen aus?
- 11. Was passiert, wenn alle Aktivitäten einer Anwendung abgeschlossen sind?
- 12. Speichern eines Werts in einer globalen Variablen
- 13. Warum werden Variablen, die in einer Case-Anweisung deklariert sind, in einem anderen Fall verwendet?
- 14. Was passiert, wenn das neue Instanzobjekt keiner Variablen zugewiesen wird?
- 15. Timer in C# mit globalen Variablen?
- 16. Die Verwaltung einer Datenbankverbindung mit einem globalen, globalen Namen verschwindet.
- 17. Was sind prozessspezifische Variablen?
- 18. Deklaration von zwei globalen Variablen mit gleichem Namen in C
- 19. Variablen deklariert mit „:“ anstelle von „=“
- 20. Wie schränke ich in C den Bereich einer globalen Variablen auf die Datei ein, in der er deklariert ist?
- 21. C++ Multithreading mit globalen Variablen verstehen
- 22. Wie viele Instanzen gibt es von statischen Variablen, die in einer Methode deklariert sind?
- 23. Alle Variablen drucken, die in einer Smarty-Vorlage verfügbar sind
- 24. SQL in Python - mit globalen Variablen
- 25. Was sind PREMERGED dll in. NET
- 26. Was sind statische Variablen?
- 27. Inner-Klasse mit globalen Variablen
- 28. Was sind die legitimen Verwendungen von globalen Tastatur-Hooks?
- 29. Assign AJAX-Aufruf zu einer globalen Variablen
- 30. Wert einer globalen Variablen zugewiesen wird (Delphi)
ist Wenn ein Prozess einen globalen Wert ändert, ist die Veränderung in einem anderen Prozess beobachtet? –
@ LB--: In der Regel nicht: Jeder Prozess seine eigene globale Variable hat *, es sei denn * Sie passieren sie im gemeinsam genutzten Speicher auf der Karte, oder einen OS-spezifischen Trick verwenden, um sie zwischen allen Prozessen gemeinsam zu machen mit, dass DLL (ich weiß nicht erinnere mich genau an den Trick auf Windows, aber es beteiligt #pragma Deklarationen, IIRC) – paercebal