2016-04-20 13 views
0

Ich habe mein unmittelbares Problem zur Hand gelöst, aber jetzt muss ich verstehen, warum es gelöst ist. ;-)DLL Entlastungsprozedur

Also hier habe ich noch ein paar Fragen.

Angenommen, ich habe eine Klasse, die aus der DLL exportiert wird. Nun sollte diese DLL in den Speicher geladen werden, jedes Mal wenn ich rufen:

MyExportedClass *pb = new MyExportedClass; 

und es sollte in Erinnerung bleiben und wird nur entladen, wenn ich rufe:

delete pb; 

Ist das richtig?

Wenn verstehe ich das richtig und die Antwort auf die vorherige Frage ist ja, was dann in dem folgende Szenario passieren soll:

Ich habe eine Schnittstelle, die von der DLL exportierte (DLL1) und ich habe deren Umsetzung der wird von einer anderen DLL (dll2) exportiert. Also jedes Mal, wenn ich ausführen:

MyInterface *pInterface = new MyImplementation; 

diese beiden DLLs sollten in dem Speicher geladen werden, und sie sollten in Erinnerung bleiben, bis ich rufe:

delete pInterface; 

Ist das richtig?

Nun, wenn die Antwort auf diese Frage ja ist - habe ich eine Kontrolle/Spruch, welche Bibliothek wird zuerst entladen und welche wird die zweite sein? Oder das Entladen geschieht immer direkt nach dem Aufruf des Destruktors der entsprechenden Klasse?

Gibt es jetzt ein Tool, das prüft, ob die Bibliothek entladen wird und an welchem ​​Punkt? Ich kann wahrscheinlich einfach die gefälschte DllMain() und überprüfen Sie ihre Prozess_Detach Fall, aber mein Eindruck war immer: Verwenden Sie DllMain, wenn die Bibliothek exportiert Funktion und nicht DllMain verwenden, wenn die Bibliothek Klassen exportiert. Ich habe diesen Ansatz seit MSVC 5/6 verwendet (nach einem der Bücher über C++).

War ich falsch, und ich kann immer DLLMain in beiden Fällen verwenden?

Vielen Dank.

+1

Warum glauben Sie, dass jede Instantiierung/Zerstörung eines Objekts das gleiche für die gesamte DLL tut? – deviantfan

+0

Mein Verständnis von Betriebssystemen sagt, dass eine DLL nur aus dem Speicher entladen wird, wenn der Speicher benötigt wird (durch eine andere DLL, ein Programm usw.). Durch das Löschen eines Objekts wird das Entladen einer DLL nicht erzwungen. –

+0

@deviantfan, nicht sicher, was du meinst. Könnten Sie bitte erläutern? – Igor

Antwort

1

DLL-Laden kann automatisch erfolgen (wenn in der Import-Tabelle aufgeführt) oder manuell (mit LoadLibrary). Einige verwaltete Frameworks, z. B. .NET, rufen im Hintergrund LoadLibrary für Sie auf, wenn sie in ihren Metadaten eine DLL-Importdeklaration sehen, C++ jedoch nicht eine davon ist. Das nächste, was C++ hat, ist Delay-Loading, wobei die Funktion, die LoadLibrary aufruft (standardmäßig kann man sie ersetzen), vom Compiler bereitgestellt wird.

Auf der anderen Seite ist DLL Entladen immer manuell. Das Löschen eines Objekts löscht niemals implizit eine DLL. Sie müssen FreeLibrary (oder FreeLibraryAndExitThread) anrufen. Und Sie sollten besser nicht FreeLibrary aufrufen, während in dieser Bibliothek definierte Objekte noch verwendet werden.

Jetzt ist das COM-System in Windows ein bisschen komplizierter, weil es DLL-Lebensdauer für Sie verwaltet. Die DLL-Lebensdauer wird jedoch nicht durch das Löschen von Objekten gesteuert, sondern durch den Aufruf einer DllCanUnloadNow-Funktion in der DLL. Normalerweise müssen Sie eine Anzahl aktiver Objekte verwalten, um diese Funktion korrekt zu schreiben.Aber es erfordert immer noch Ihre manuelle Implementierung, und Sie können einfach immer false zurückgeben, um nie zu entladen (das ist ein bisschen ein Schmerz während der Entwicklung, weil Sie die gesamte Anwendung schließen müssen, um eine neue Plugin-Version usw. zu testen) jede Verwendung einer DLL und das erfolgreiche Entladen ist sowieso selten)

Und sicherlich gibt es nichts, das automatisch eine in der Importtabelle aufgelistete DLL entlädt, die beim Prozessstart geladen und nie entladen wird, egal wie viele Objektinstanzen werden erstellt oder zerstört.

+0

Muss ich FreeLibrary {AndExitThread}() aufrufen? Was passiert, wenn ich es nicht tue? Wird OS dafür sorgen? Denken Sie daran, ich exportiere nicht die Funktion, wo ich die Funktion aufrufen und über die Bibliothek vergessen - ich exportiere eine C++ - Klasse, die von Zeiger instanziiert wird. Also, wenn ich die DLL nicht entlade, was passiert? Wird OS dafür sorgen, dass niemand auf die DLL verweist? AFAIU, dies ist ein Modul-Handle, das nicht freigegeben wird, also wird es ein Ressourcenleck sein, oder? – Igor

+0

@Igor: Wenn der Prozess beendet wird, werden seine DLLs vom Betriebssystem freigegeben. Wenn Sie 'FreeLibrary' nicht aufrufen, bleibt die DLL so lange im Speicher, wie der Prozess läuft. Sie können davon ausgehen, dass ein Ressourcenverlust auftritt, aber nur einmal, unabhängig von der Anzahl der Klasseninstanzen und -funktionen aus der DLL, die Sie verwenden, daher ist dies nicht von Bedeutung. Wenn Leute über Speicherleckfehler sprechen, sprechen sie von Lecks, die jedes Mal auftreten, wenn eine Operation läuft und sich mit der Zeit anhäuft. –

+0

Danke für eine Erklärung. – Igor