Frage

Wenn eine Klassenbibliothek in C ++ erstellen, können Sie zwischen dynamischer wählen (.dll, .so) und statischen (.lib, .a) Bibliotheken. Was ist der Unterschied zwischen ihnen und wenn es angemessen zu verwenden ist, das?

War es hilfreich?

Lösung

Statische Bibliotheken erhöhen die Größe des Codes in die Binärdatei. Sie sind immer geladen und was auch immer Version des Codes Sie zusammengestellt mit der Version des Codes, der ausgeführt wird.

Dynamische Bibliotheken werden getrennt gelagert und versioniert. Es ist möglich, dass eine Version der dynamischen Bibliothek geladen werden, das war nicht das Original, die mit Ihrem Code ausgeliefert , wenn das Update binär als kompatibel mit der ursprünglichen Version.

Zusätzlich dynamische Bibliotheken sind nicht unbedingt geladen - sie sind in der Regel geladen, wenn zuerst genannt -. Und kann unter den Komponenten, die die gleiche Bibliothek (mehrere Datenlasten, eine Code Last) verwenden gemeinsam genutzt werden

Dynamische Bibliotheken wurden als die bessere Lösung sein, die meiste Zeit, aber ursprünglich hatten sie einen großen Fehler (google DLL Hölle), die alle haben aber durch neuere Windows-Betriebssysteme (Windows XP insbesondere) eliminiert.

Andere Tipps

Andere haben ausreichend erklärt, was eine statische Bibliothek ist, aber ich mag die Verwendung von statischen Bibliotheken einige der Einschränkungen, darauf hinzuweisen, zumindest unter Windows:

  • Singletons: Wenn etwas sein, global / statisch und einzigartig muss sehr vorsichtig sein, um es in einer statischen Bibliothek setzen. Wenn mehrere DLLs gegen diese statische Bibliothek verknüpft sind, werden sie erhalten jeweils ihre eigene Kopie des Singletons. Allerdings, wenn Ihre Anwendung eine einzelne EXE ohne benutzerdefinierten DLLs ist, kann dies kein Problem sein.

  • Nicht referenzierte Code Entfernung: Wenn Sie eine statische Bibliothek verknüpfen gegen, nur die Teile der statischen Bibliothek, die von Ihrer DLL referenziert wird / werden EXE in Ihre DLL / EXE verlinkt wird.

    Zum Beispiel, wenn mylib.lib enthält a.obj und b.obj und Ihre DLL / EXE nur Verweise Funktionen oder Variablen aus a.obj, wird die gesamte b.obj vom Linker verworfen bekommen. Wenn b.obj global / statische Objekte enthält, deren Konstruktoren und Destruktoren nicht ausgeführt werden sollen. Wenn diese Konstruktoren / Destruktoren Nebenwirkungen haben, können Sie durch ihre Abwesenheit enttäuscht werden.

    Auch wenn die statische Bibliothek enthält spezielle Einstiegspunkte Sie müssen darauf achten, dass sie tatsächlich enthalten sind. Ein Beispiel hierfür in Embedded-Programmierung (okay, nicht Windows) wäre ein Interrupt-Handler, die als an einer bestimmten Adresse gekennzeichnet ist. Sie müssen auch den Interrupt-Handler als Einstiegspunkt markieren sicherzustellen, dass es nicht verworfen bekommt.

    Eine weitere Folge davon ist, dass eine statische Bibliothek Objektdateien enthält, die aufgrund unaufgelösten Referenzen völlig unbrauchbar sind, aber es wird keine Linker-Fehler verursachen, bis Sie eine Funktion oder Variable aus diesen Objektdateien verweisen. Dies kann geschehen, lange nachdem die Bibliothek geschrieben wird.

  • Debug-Symbole: Sie können für jede statische Bibliothek einen separaten PDB möchten, oder Sie können die Debug-Symbole wollen in den Objektdateien platziert werden, so dass sie in die PDB gerollt erhalten für die DLL / EXE-Datei. Die Visual C ++ Dokumentation erklärt die notwendigen Optionen .

  • RTTI: Sie können mit mehreren type_info Objekte für die gleiche Klasse am Ende, wenn Sie eine einzelne statische Bibliothek in mehrere DLLs verknüpfen. Wenn Ihr Programm geht davon aus, dass type_info „Singletons“ Daten und verwendet &typeid() oder type_info::before(), können Sie unerwünschte und überraschende Ergebnisse erzielen.

Eine lib ist eine Einheit des Code, der in Ihrer Anwendung ausführbare Datei gebündelt wird.

Eine DLL ist eine eigenständige Einheit von ausführbarem Code. Es wird nur in dem Prozess geladen, wenn ein Anruf in diesen Code gemacht wird. Eine DLL kann von mehreren Anwendungen und geladen in mehreren Prozessen verwendet werden, während nach wie vor nur eine Kopie des Codes auf der Festplatte hat.

Dll Profis : kann zur Wiederverwendung / share Code zwischen mehreren Produkten verwendet werden; laden in den Prozessspeicher auf Nachfrage und kann entladen werden, wenn sie nicht benötigt wird; kann unabhängig vom Rest des Programms aufgerüstet werden.

Dll cons : Auswirkungen auf die Leistung der DLL Laden und Code Rebasing; Versionierungsprobleme ( "DLL-Hölle")

Lib Profis : als Code keine Auswirkung auf die Leistung immer in den Prozess geladen wird und nicht indexiert; keine Versionsprobleme.

Lib cons : ausführbar / process "aufblasen" - die gesamte Code ist in der ausführbaren Datei und wird beim Prozess geladen beginnen; keine Wiederverwendung / Sharing -. jedes Produkt seine eigene Kopie des Codes hat

Neben den technischen Auswirkungen von statischen vs dynamischen Bibliotheken (statische Dateien bündeln alles in einer großen binären vs dynamischen Bibliotheken, das Code-Sharing zwischen mehreren verschiedenen ausführbaren Dateien erlauben), gibt es die rechtlichen Auswirkungen .

Zum Beispiel, wenn Sie mit LGPL-Code lizenziert und verknüpfen Sie statisch gegen eine LGPL-Bibliothek (und somit eine große binäre erstellen), der Code wird automatisch Open Source ( frei wie in Freiheit) LGPL-Code. Wenn Sie ein gemeinsam genutzte Objekte verknüpfen gegen, dann müssen Sie nur die Verbesserungen / Fehlerkorrekturen LGPL, die Sie die LGPL-Bibliothek machen selbst.

Dies wird zu einer weit wichtigeren Frage, wenn Sie entscheiden, wie Sie zum Beispiel mobile Anwendungen zu kompilieren (in Android Sie eine Auswahl an statischen haben vs dynamisch, in iOS Sie dies nicht tun - es ist immer statisch ist).


Erstellen einer statische Bibliothek

$$:~/static [32]> cat foo.c
#include<stdio.h>
void foo()
{
printf("\nhello world\n");
}
$$:~/static [33]> cat foo.h
#ifndef _H_FOO_H
#define _H_FOO_H

void foo();

#endif
$$:~/static [34]> cat foo2.c
#include<stdio.h>
void foo2()
{
printf("\nworld\n");
}
$$:~/static [35]> cat foo2.h
#ifndef _H_FOO2_H
#define _H_FOO2_H

void foo2();

#endif
$$:~/static [36]> cat hello.c
#include<foo.h>
#include<foo2.h>
void main()
{
foo();
foo2();
}
$$:~/static [37]> cat makefile
hello: hello.o libtest.a
        cc -o hello hello.o -L. -ltest
hello.o: hello.c
        cc -c hello.c -I`pwd`
libtest.a:foo.o foo2.o
        ar cr libtest.a foo.o foo2.o
foo.o:foo.c
        cc -c foo.c
foo2.o:foo.c
        cc -c foo2.c
clean:
        rm -f foo.o foo2.o libtest.a hello.o

$$:~/static [38]>

Erstellen einer dynamische Bibliothek

$$:~/dynamic [44]> cat foo.c
#include<stdio.h>
void foo()
{
printf("\nhello world\n");
}
$$:~/dynamic [45]> cat foo.h
#ifndef _H_FOO_H
#define _H_FOO_H

void foo();

#endif
$$:~/dynamic [46]> cat foo2.c
#include<stdio.h>
void foo2()
{
printf("\nworld\n");
}
$$:~/dynamic [47]> cat foo2.h
#ifndef _H_FOO2_H
#define _H_FOO2_H

void foo2();

#endif
$$:~/dynamic [48]> cat hello.c
#include<foo.h>
#include<foo2.h>
void main()
{
foo();
foo2();
}
$$:~/dynamic [49]> cat makefile
hello:hello.o libtest.sl
        cc -o hello hello.o -L`pwd` -ltest
hello.o:
        cc -c -b hello.c -I`pwd`
libtest.sl:foo.o foo2.o
        cc -G -b -o libtest.sl foo.o foo2.o
foo.o:foo.c
        cc -c -b foo.c
foo2.o:foo.c
        cc -c -b foo2.c
clean:
        rm -f libtest.sl foo.o foo

2.o hello.o
$$:~/dynamic [50]>

C ++ Programme gebaut werden in zwei Phasen

  1. Compilation - erzeugt Objektcode (OBJ)
  2. Verknüpfung - erzeugt ausführbaren Code (EXE- oder DLL)

Statische Bibliothek (LIB) ist nur ein Bündel von OBJ-Dateien und ist daher nicht ein komplettes Programm. Es hat nicht die zweite (Verknüpfung) Phase des Aufbaus eines Programms unterzogen. Dlls, auf der anderen Seite, sind wie exe und sind daher vollständige Programme.

Wenn Sie eine statische Bibliothek zu bauen, ist es noch nicht verknüpft und damit die Verbraucher Ihrer statischen Bibliothek den gleichen Compiler verwenden, die Sie verwenden (wenn Sie g ++ verwendet, werden sie g verwenden ++).

Wenn Sie stattdessen gebaut Sie eine DLL (und baute es

Sie sollten sorgfältig über Änderungen im Laufe der Zeit, Versionierung, Stabilität, Kompatibilität, etc.

Wenn es zwei Anwendungen, die den gemeinsamen Code verwenden, tun Sie diese Anwendungen zwingen wollen, zusammen zu ändern, falls sie müssen miteinander kompatibel sein? Dann nutzen Sie die dll. Alle exe sein wird, den gleichen Code.

Oder wollen Sie sie voneinander isolieren wollen, so dass Sie ein ändern können und sicher sein, Sie nicht die anderen gebrochen haben. Dann nutzen Sie die statische lib.

DLL Hölle ist, wenn Sie wahrscheinlich eine statische lib verwendet haben sollte, aber man verwendet statt dessen eine dll, und nicht alle EXE-Dateien sind kompatibel, mit ihm.

Eine statische Bibliothek wird in den Client zusammengestellt. A LIB wird bei der Kompilierung und der Inhalt der Bibliothek wird Teil der raubend ausführbaren verwendet.

Eine dynamische Bibliothek wird zur Laufzeit geladen und nicht in das Client-Programm kompiliert. Dynamische Bibliotheken sind flexibler als mehrere Client-ausführbare Dateien eine DLL laden und seine Funktionalität nutzen. Dies hält auch die Gesamtgröße und Wartbarkeit Ihres Client-Code auf ein Minimum.

Eine statische Bibliothek muss in die endgültige ausführbare Datei verknüpft werden; es wird Teil der ausführbaren Datei und folgt ihm, wo immer es geht. Eine dynamische Bibliothek wird jedes Mal geladen die ausführbaren Datei ausgeführt wird und bleibt getrennt von der ausführbaren Datei als DLL-Datei.

Sie würden eine DLL verwenden, wenn Sie von der Bibliothek zur Verfügung gestellt in die Lage sein wollen, um die Funktionalität zu ändern, ohne die ausführbare Datei neu zu verknüpfen (nur die DLL-Datei ersetzen, ohne die ausführbare Datei ersetzen zu müssen).

Sie würden eine statische Bibliothek verwenden, wenn Sie eine dynamische Bibliothek keinen Grund haben, zu verwenden.

Ulrich Drepper Arbeit über „ Wie Shared Libraries schreiben“ ist auch eine gute Ressource, besten Details, wie die Vorteile von gemeinsam genutzten Bibliotheken zu nehmen, oder was er bezeichnet als „Dynamic Shared Objects“ (DSOs). Es konzentriert sich mehr auf gemeinsam genutzte Bibliotheken in der ELF Binärformat, aber einige Diskussionen sind geeignet für Windows DLLs gut.

Für eine ausgezeichnete Diskussion über dieses Thema hat gelesen von diesen Artikel hier .

Wirklich das Trade-off Sie (in einem großen Projekt) machen ist in der anfänglichen Ladezeit, die Bibliotheken zu einer Zeit oder einem anderen verlinkt werden wollen, dass die Entscheidung getroffen werden muss, ist nimmt die Verbindung lange genug, dass der Compiler muss die Kugel und tut es nach vorne beißen, oder kann der dynamische Linker tut es zur Ladezeit.

Wenn Ihre Bibliothek wird unter mehreren ausführbaren Dateien gemeinsam genutzt wird, ist es oft sinnvoll, es dynamisch zu machen, die Größe der ausführbaren Dateien zu reduzieren. Ansonsten definitiv es statisch machen.

Es gibt mehrere Nachteile einer DLL verwenden. Es gibt zusätzlichen Aufwand für die Be- und Entladen es. Es gibt auch eine zusätzliche Abhängigkeit. Wenn Sie die DLL ändern, um es mit Ihrem executalbes unvereinbar zu machen, werden sie aufhören zu arbeiten. Auf der anderen Seite, wenn Sie eine statische Bibliothek zu ändern, kompilierten ausführbare Dateien, die alte Version verwenden, werden nicht berührt.

Wenn die Bibliothek statisch ist, dann wird der Code zur Verbindungszeit mit ausführbaren eingebunden. Dies macht die ausführbare Datei größer (als wenn Sie die dynamische Route ging).

Wenn die Bibliothek dynamisch ist dann zu Verbindungszeit Verweisen auf die erforderlichen Methoden gebaut werden, um die ausführbare Datei. Dies bedeutet, dass Sie die ausführbare Datei versenden und die dynamische Bibliothek. Sie sollten auch auf den Code in der Bibliothek, ob gemeinsamen Zugriff prüfen, ist sicher, bevorzugt Ladeadresse unter anderem Zeug.

Wenn Sie mit der statischen Bibliothek leben können, mit der statischen Bibliothek gehen.

Statische Bibliotheken sind Archive, die den Objektcode für die Bibliothek enthalten, wenn sie in einer Anwendung verknüpft, die Code in der ausführbaren Datei kompiliert wird. Shared Libraries sind unterschiedlich, dass sie nicht in die ausführbare Datei kompiliert. Stattdessen wird der dynamische Linker sucht einige Verzeichnisse für die Bibliothek suchen (n) braucht es, lädt dann, dass in dem Speicher. Mehr als eine ausführbare Datei kann das gleiche gemeinsam genutzte Bibliothek zur gleichen Zeit verwenden, wodurch die Speichernutzung und ausführbare Größe reduziert wird. Allerdings gibt es dann mehr Dateien mit der ausführbaren Datei zu verteilen. Sie müssen sicherstellen, dass die Bibliothek auf das uses System irgendwo installiert ist, wo der Linker es, statisch Linke beseitigen dieses Problem, aber die Ergebnisse in einer größeren ausführbaren Datei finden kann.

Wenn Sie Ihre Arbeit an Embedded-Projekten oder spezialisierte Plattformen statischen Bibliotheken sind der einzige Weg zu gehen, auch oft sie weniger umständlich sind in Ihre Anwendung zu kompilieren. Auch Projekte und Make-Datei, die das alles macht das Leben glücklicher sind.

Wir verwenden eine Menge DLL (> 100) in unserem Projekt. Diese DLL haben Abhängigkeiten voneinander und deshalb haben wir uns für den Aufbau von dynamischer Verknüpfung. Allerdings hat es die folgenden Nachteile auf:

  • langsamer Start (> 10 Sekunden)
  • DLL hatte versioniert werden, da Fenster lädt Module auf Eindeutigkeit der Namen. Eigene geschrieben Komponenten würden sonst die falsche Version der DLL erhalten (das heißt die man bereits statt seiner eigenen verteilten Satz geladen)
  • Optimierer kann nur innerhalb DLL Grenzen optimieren. Zum Beispiel der Optimierer häufig verwendete Daten und Code nebeneinander zu platzieren versucht, aber das wird über DLL Grenzen nicht funktioniert

Vielleicht ein besseres Setup war zu machen alles eine statische Bibliothek (und damit nur Sie eine ausführbare Datei haben). Dies funktioniert nur, wenn keine Code-Duplizierung stattfindet. Ein Test scheint diese Annahme zu unterstützen, aber ich konnte keine offizielle MSDN finden. So zum Beispiel macht 1 exe mit:

  • exe verwendet shared_lib1, shared_lib2
  • shared_lib1 Verwendung shared_lib2
  • shared_lib2

Der Code und Variablen von shared_lib2 sollten nur einmal in den letzten fusionierten ausführbaren vorhanden sein. Kann mir jemand diese Frage unterstützen?

würde ich eine Faustregel geben, dass, wenn Sie eine große Codebasis haben, die alle auf der unteren Ebene Bibliotheken gebaut (zB ein Utils oder GUI-Framework), die Sie in überschaubare Bibliotheken partitionieren wollen, dann machen sie statische Bibliotheken. Dynamische Bibliotheken nicht wirklich kaufen Sie etwas und es gibt weniger Überraschungen - es gibt nur eine Instanz von Singletons zum Beispiel sein wird.

Wenn Sie eine Bibliothek haben, die mit dem Rest der Codebasis völlig getrennt ist (zB eine Dritte Bibliothek), dann halte es für eine dll zu machen. Wenn die Bibliothek LGPL ist, müssen Sie möglicherweise eine DLL ohnehin zu den Lizenzbedingungen aufgrund verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top