Wenn Sie eine Klassenbibliothek in C++ erstellen, können Sie zwischen dynamischen ( .dll
, .so
) und statisch ( .lib
, .a
) Bibliotheken. Was ist der Unterschied zwischen diesen Bibliotheken und wann ist es sinnvoll, welche zu verwenden?
Antworten
Zu viele Anzeigen?Statische Bibliotheken erhöhen die Größe des Codes in Ihrer Binärdatei. Sie werden immer geladen und die Version des Codes, mit der Sie kompiliert haben, ist die Version des Codes, die ausgeführt wird.
Dynamische Bibliotheken werden separat gespeichert und versioniert. Es ist möglich, dass eine Version der dynamischen Bibliothek geladen wird, die nicht die ursprüngliche Version ist, die mit Ihrem Code geliefert wurde si die Aktualisierung wird als binärkompatibel mit der ursprünglichen Version angesehen.
Außerdem müssen dynamische Bibliotheken nicht unbedingt geladen werden - sie werden in der Regel beim ersten Aufruf geladen - und können von Komponenten, die dieselbe Bibliothek verwenden, gemeinsam genutzt werden (mehrere Daten werden geladen, ein Code wird geladen).
Dynamische Bibliotheken galten die meiste Zeit als der bessere Ansatz, aber ursprünglich hatten sie einen großen Makel (siehe DLL-Hölle), der bei neueren Windows-Betriebssystemen (insbesondere Windows XP) fast vollständig beseitigt wurde.
Andere haben bereits hinreichend erklärt, was eine statische Bibliothek ist, aber ich möchte auf einige der Nachteile der Verwendung statischer Bibliotheken hinweisen, zumindest unter Windows:
-
Einzelpersonen: Wenn etwas global/statisch und einzigartig sein muss, sollte man sehr vorsichtig sein, es in eine statische Bibliothek zu packen. Wenn mehrere DLLs gegen diese statische Bibliothek gelinkt werden, erhält jede ihre eigene Kopie des Singletons. Wenn es sich bei Ihrer Anwendung jedoch um eine einzelne EXE ohne benutzerdefinierte DLLs handelt, stellt dies möglicherweise kein Problem dar.
-
Entfernung von nicht referenziertem Code: Wenn Sie gegen eine statische Bibliothek linken, werden nur die Teile der statischen Bibliothek, die von Ihrer DLL/EXE referenziert werden, in Ihre DLL/EXE gelinkt.
Zum Beispiel, wenn
mylib.lib
enthälta.obj
yb.obj
und Ihre DLL/EXE nur auf Funktionen oder Variablen ausa.obj
die Gesamtheit derb.obj
wird vom Linker verworfen. Wennb.obj
globale/statische Objekte enthält, werden deren Konstruktoren und Destruktoren nicht ausgeführt. Wenn diese Konstruktoren/Destruktoren Seiteneffekte haben, könnten Sie über ihr Fehlen enttäuscht sein.Wenn die statische Bibliothek spezielle Einstiegspunkte enthält, müssen Sie unter Umständen darauf achten, dass diese auch tatsächlich eingebunden werden. Ein Beispiel hierfür wäre in der eingebetteten Programmierung (okay, nicht Windows) ein Interrupt-Handler, der als an einer bestimmten Adresse liegend markiert ist. Sie müssen auch den Interrupt-Handler als Einstiegspunkt markieren, um sicherzustellen, dass er nicht verworfen wird.
Eine weitere Folge davon ist, dass eine statische Bibliothek Objektdateien enthalten kann, die aufgrund nicht aufgelöster Referenzen völlig unbrauchbar sind, aber keinen Linker-Fehler verursachen, bis Sie eine Funktion oder Variable aus diesen Objektdateien referenzieren. Dies kann lange nach dem Schreiben der Bibliothek geschehen.
-
Debug-Symbole: Möglicherweise möchten Sie eine separate PDB für jede statische Bibliothek, oder Sie möchten, dass die Debugsymbole in den Objektdateien platziert werden, so dass sie in die PDB für die DLL/EXE aufgenommen werden. Die Visual C++-Dokumentation erklärt die notwendigen Optionen .
-
RTTI: Möglicherweise haben Sie am Ende mehrere
type_info
Objekte für dieselbe Klasse, wenn Sie eine einzelne statische Bibliothek mit mehreren DLLs verknüpfen. Wenn Ihr Programm annimmt, dasstype_info
sind "Singleton"-Daten und verwenden&typeid()
otype_info::before()
können Sie unerwünschte und überraschende Ergebnisse erzielen.
Eine Lib ist eine Codeeinheit, die in der ausführbaren Datei Ihrer Anwendung gebündelt ist.
Eine DLL ist eine eigenständige Einheit von ausführbarem Code. Sie wird nur dann in den Prozess geladen, wenn ein Aufruf in diesen Code gemacht wird. Eine DLL kann von mehreren Anwendungen verwendet und in mehreren Prozessen geladen werden, wobei sich immer nur eine Kopie des Codes auf der Festplatte befindet.
Dll-Profis Die Software kann verwendet werden, um Code zwischen mehreren Produkten wiederzuverwenden/zu teilen; sie wird bei Bedarf in den Prozessspeicher geladen und kann entladen werden, wenn sie nicht benötigt wird; sie kann unabhängig vom Rest des Programms aktualisiert werden.
Dll Nachteile Leistungseinbußen durch das Laden von DLLs und die Neubasierung von Code; Versionsprobleme ("DLL-Hölle")
Lib-Profis Keine Auswirkung auf die Leistung, da der Code immer in den Prozess geladen wird und nicht neu basiert wird; keine Probleme mit der Versionierung.
Freiheitsentzug Der gesamte Code befindet sich in Ihrer ausführbaren Datei und wird beim Start des Prozesses geladen; keine Wiederverwendung/Weitergabe - jedes Produkt hat seine eigene Kopie des Codes.
C++-Programme werden in zwei Phasen erstellt
- Kompilierung - erzeugt Objektcode (.obj)
- Verknüpfung - erzeugt ausführbaren Code (.exe oder .dll)
Eine statische Bibliothek (.lib) ist nur ein Bündel von .obj-Dateien und ist daher kein vollständiges Programm. Sie hat die zweite Phase (Linking) der Programmerstellung nicht durchlaufen. Dlls hingegen sind wie Exe-Dateien und daher vollständige Programme.
Wenn Sie eine statische Bibliothek erstellen, ist diese noch nicht gelinkt und daher müssen die Nutzer Ihrer statischen Bibliothek denselben Compiler verwenden, den Sie verwendet haben (wenn Sie g++ verwendet haben, müssen sie auch g++ verwenden).
Wenn Sie stattdessen eine DLL erstellen (und sie richtig ), haben Sie ein vollständiges Programm erstellt, das alle Verbraucher nutzen können, unabhängig davon, welchen Compiler sie verwenden. Es gibt jedoch einige Einschränkungen für den Export aus einer DLL, wenn eine kompilerübergreifende Kompatibilität gewünscht ist.
Neben den technischen Implikationen von statischen und dynamischen Bibliotheken (statische Dateien bündeln alles in einer großen Binärdatei, während dynamische Bibliotheken die gemeinsame Nutzung von Code durch verschiedene ausführbare Dateien ermöglichen), gibt es die rechtliche Implikationen .
Wenn Sie zum Beispiel LGPL-lizenzierten Code verwenden und statisch gegen eine LGPL-Bibliothek linken (und damit eine große Binärdatei erstellen), wird Ihr Code automatisch Open Sourced ( frei wie in Freiheit) LGPL-Code. Wenn Sie gegen ein gemeinsam genutztes Objekt linken, müssen Sie nur die Verbesserungen/Fehlerbehebungen, die Sie an der LGPL-Bibliothek selbst vornehmen, unter LGPL stellen.
Dies wird zu einem weitaus wichtigeren Thema, wenn Sie zum Beispiel entscheiden, wie Sie Ihre mobilen Anwendungen kompilieren sollen (bei Android haben Sie die Wahl zwischen statisch und dynamisch, bei iOS nicht - es ist immer statisch).
- See previous answers
- Weitere Antworten anzeigen