Mein Programm verwendet dlopen
, um ein gemeinsames Objekt zu laden, und später dlclose
, um es zu entladen. Manchmal wird dieses gemeinsame Objekt erneut geladen. Ich habe bemerkt, dass statische Variablen nicht neu initialisiert werden (etwas, was für mein Programm entscheidend ist), also fügte ich einen Test ( dlopen
mit RTLD_NOLOAD
) nach dlclose
hinzu, um zu sehen, ob die Bibliothek wirklich entladen ist. Sicher genug, es war immer noch in Erinnerung.
Ich habe dann versucht, dlclose
wiederholt aufzurufen, bis die Bibliothek wirklich entladen ist, aber was ich bekam, war eine Endlosschleife. Dies ist der Code, mit dem ich überprüfe, ob die Bibliothek entladen wurde:
Meine Frage ist, was sind die möglichen Gründe dafür, dass mein geteiltes Objekt nicht nach dlclose
entladen wird, da meine dlopen
-Aufrufe die einzigen Stellen sind, an denen es geladen wird. Können Sie eine Vorgehensweise vorschlagen, um die Ursache des Problems zu finden? Warum haben wiederholte Aufrufe von dlclose
keinen Effekt? Sie dekrementieren die Referenzzählung, nicht wahr?
BEARBEITEN: Habe gerade herausgefunden, dass dies nur passiert, wenn ich mit gcc kompiliere. Mit clang ist alles in Ordnung.
Der POSIX-Standard erfordert tatsächlich nicht, dass dlclose
eine Bibliothek aus dem Adressraum entlädt:
Obwohl eine dclclose () - Operation zum Entfernen von Strukturen nicht erforderlich ist von einem Adressraum ist auch keine Implementierung verboten so tun.
Quelle: Die Open Group Base Spezifikationen Ausgabe 6
Das bedeutet anders als das Handle ungültig zu machen, dlclose
muss gar nichts tun.
Manchmal wird das Entladen auch vom System verzögert, es markiert lediglich die Bibliothek als "entfernt" und führt diese Operation zu einem späteren Zeitpunkt aus (aus Gründen der Effizienz oder weil es momentan einfach nicht möglich ist, diese Operation auszuführen) ). Wenn Sie jedoch dlopen
erneut aufrufen, bevor es ausgeführt wurde, wird das Flag gelöscht und die noch geladene Bibliothek wird erneut verwendet.
In einigen Fällen weiß das System sicher, dass einige Symbole der Bibliothek noch verwendet werden, in diesem Fall wird es nicht aus dem Adressraum entladen, um hängende Zeiger zu vermeiden. In einigen Fällen weiß das System nicht sicher, ob sie in Verwendung sind, aber es kann auch unmöglich sicher sagen, dass sie es nicht sind, es ist besser als Nachsicht, es wird diese Bibliothek niemals wirklich aus dem Speicher entfernen .
Es gibt noch andere obskure Fälle, abhängig von der Art des Betriebssystems und oft auch von der Version. Z.B. Ein übliches Linux-Problem besteht darin, dass wenn Sie eine Bibliothek erstellt haben, die STB_GNU_UNIQUE-Symbole verwendet, diese Bibliothek als "nicht entladen" gekennzeichnet ist und daher niemals entladen wird. Siehe hier , hier ( DF_1_NODELETE
bedeutet nicht ausladbar) und hier . Es kann also auch davon abhängen, welche Symbole oder welche Art von Symbolen ein Compiler generiert. Versuchen Sie, readelf -Ws
in Ihrer Bibliothek auszuführen und suchen Sie nach Objekten, die als UNIQUE
getaggt sind.
Im Allgemeinen können Sie sich nicht wirklich darauf verlassen, dass dlclose
wie erwartet funktioniert. In der Praxis sah ich es öfter "scheitern" als "erfolgreich" in den letzten zehn Jahren (naja, es ist nie wirklich gescheitert, es hat oft die Bibliothek nicht aus dem Gedächtnis entladen; doch es funktionierte wie von den Standards gefordert). p>
Beim Laden dynamischer Bibliotheken gibt es viele Besonderheiten. Sich darauf zu verlassen, dass das Betriebssystem statische Variablen initialisiert, ist mit Problemen behaftet. Es ist viel besser, entweder alles zu vermeiden oder einen Plugin-Loader zu verwenden, der alle Spezialfälle für Sie erledigt.
Ich empfehle Ihnen, sich glib-Module anzuschauen. Glib bietet eine plattformunabhängige Möglichkeit, dynamische Bibliotheken zu laden. Sie können diese Rückrufe verwenden:
Sie können Ressourcen allozieren und freigeben. Anstatt sich auf das Betriebssystem zu verlassen, um die Statik zuverlässig zuzuweisen, können Sie dynamisch die benötigten Daten zuweisen.
Sie müssen diese Funktionen nur in Ihrer dynamischen Bibliothek definieren und dann laden und entladen: