Sind statische C-Bibliotheken verpönt? [geschlossen]

11

Es gibt zwei Argumente für gemeinsam genutzte Bibliotheken:

  1. Es hilft, Speicherplatz zu reduzieren.
  2. Wenn eine gemeinsam genutzte Bibliothek aktualisiert wird, werden alle davon abhängigen Binärdateien aktualisiert.

Es gibt hauptsächlich einen Nachteil für gemeinsam genutzte Bibliotheken:

  • Sie können die Abhängigkeitshölle einführen.

Auf Desktop-Computern hält der erste Vorteil nicht mehr wirklich an. Die Verschwendung von Speicherplatz ist heutzutage kein großes Problem.

Mit statischen Binärdateien könnten wir viel bessere Paketmanager finden - ich meine, die Hölle der Abhängigkeit würde der Vergangenheit angehören. Das Hinzufügen eines Programms würde nur das Hinzufügen einer Binärdatei bedeuten. schließlich ein Ordner, damit er seine Dateien verarbeiten kann. Das Löschen eines Programms würde einfach das Löschen dieser Datei bedeuten. Abhängigkeiten? Weg.

Der zweite Vorteil bleibt bestehen, aber ich denke, der Vorteil statischer Binärdateien auf Desktop-Computern überwiegt. Ich meine, sogar neue Sprachen wie Go kompilieren alle ihre Binärdateien trotz der Vorteile der gemeinsam genutzten Bibliotheken aufgrund der Bequemlichkeit.


Sind statische C-Bibliotheken immer noch verpönt, da einer der Hauptvorteile von gemeinsam genutzten Bibliotheken keine große Sache mehr ist? Wenn ja warum?

Florian Margaine
quelle
4
Der Hauptgrund, warum C nicht mehr verwendet wird, liegt darin, dass Sie nicht an modernen Desktop-Computern arbeiten.
Telastyn
18
@ Telastyn Es tut mir leid? Der größte Teil der auf meinen Desktop-Computern installierten Software ist in C. geschrieben
Florian Margaine
6
6
Ein Vorteil dynamischer Bibliotheken besteht darin, dass Benutzer die Bibliotheken weiterhin aktualisieren können, um Fehler, Sicherheitslücken oder Hardwareprobleme in Ihrem 15 Jahre alten Closed-Source-Spiel zu umgehen, das längst keine Updates mehr erhält. Eine Art Nischenfall, aber da gute Spiele keine Ware sind, hilft "benutze einfach ein anderes Programm" nicht wirklich. Es ist auch wichtig, LGPL einzuhalten, ohne Open Sourcing für Ihren eigenen Code.
Doval
4
Sie haben zwei weitere Vorteile der gemeinsam genutzten Bibliotheken vergessen: 1) Sie werden auch im Speicher gemeinsam genutzt. 2) Alle Linker saugen schlecht, und das Verknüpfen einer riesigen Binärdatei ist äußerst unangenehm. Das Aufteilen einer Binärdatei in mehrere kleinere Entitäten macht den gesamten Prozess viel erträglicher.
SK-Logik

Antworten:

9

Die Prämisse Ihrer Frage ist fehlerhaft. Was verpönt ist, ist, sich an Doktrinäre und Absolute zu halten, ohne die Grundlage dahinter zu verstehen (Cargo Cult Programming?).

Die verknüpfte SO-Antwort ist eine interessante Studie zu diesem Thema. In der Frage ging es darum, warum eine Kompilierung mit der Option -static nicht funktioniert. Die Antwort, mit der Sie verknüpft haben, war nichts anderes als ein Schimpfen darüber, keine statische Verknüpfung zu verwenden. Wenn nicht diskutiert wird, warum es schlecht ist, und verlangt, dass das OP dynamische Verknüpfung verwendet. Es ist bedauerlich, dass es als die richtige Antwort markiert ist (die folgende Antwort hat doppelt so viele Stimmen und ist die richtige Antwort auf die Frage des OP), denn obwohl die richtige Antwort da ist, ist sie tief in einer dogmatischen Meinung verborgen.

Die eigentliche Frage ist, was die Vor- und Nachteile einer statischen oder dynamischen Verknüpfung sind und wann eine der anderen vorgezogen wird.

mattnz
quelle
2
Basile Antwort tut man genau sagen , warum er empfiehlt Shared Libraries mit: ? „Warum Sie verknüpfen mögen Ihre Anwendung statisch . Im Allgemeinen ist es ein Fehler , (weil Sie von Aktualisierungen der System dynamischen Bibliotheken nicht profitieren tun) Insbesondere Name Service Switch Einrichtungen von libc wollen dynamische Bibliotheken. " Es ist kein" Schimpfen ", nur weil Sie damit nicht einverstanden sind.
Cody Gray
@Cody Die mit verlinkte Antwort wurde bearbeitet, seit ich sie als Schimpfen bezeichnet habe. Die einzige Meinung, die ich zu statischen und dynamischen Verknüpfungen habe, ist, die für Ihre Bedürfnisse geeignete zu verwenden und die Stärken und Schwächen der Wahl zu verstehen, anstatt in die Programmierdoktrin des Frachtkultes zu fallen, weil "jemand dies gesagt hat".
Mattnz
Ja, der Teil "Insbesondere ..." wurde hinzugefügt. Ich bin mir nicht sicher, wie sich das auf den Rant-Status auswirkt. Natürlich befürworte ich keine Frachtkultprogrammierung. Es ist nur so, dass Befürworter der statischen Verknüpfung (meiner Erfahrung nach) die Sicherheitsbedenken oft übersehen oder unterschätzen. Statische Verknüpfungen können für einmalige Dienstprogramme sehr gut geeignet sein, wodurch die App in sich geschlossen und damit die Verteilung erheblich vereinfacht wird. Aber jede App, die weit verbreitet ist oder für die Produktion verwendet wird, sollte wirklich mit einer gemeinsam genutzten Bibliothek verknüpft sein. Es gibt keine wirklichen Nachteile: Auf dieser App-Ebene benötigen Sie bereits einen Bereitstellungsprozess.
Cody Gray
1
Ein gutes Beispiel dafür, wo statische Verknüpfungen angebracht sind, ist, wo ich arbeite - große, komplexe lebenskritische Systeme. Sobald ein kritisches Modul getestet und für den Betrieb freigegeben wurde, darf sich sein Verhalten nicht ändern, ohne den Prozess zu durchlaufen. Keine betrieblichen und nicht lebenswichtigen Teile des Systems (Abrechnung und Berichterstellung) benötigen jedoch eine weniger robuste Steuerung und verwenden eine dynamische Verknüpfung.
Mattnz
7

Aus Entwicklersicht kann die dynamische Verknüpfung Ihre Kompilierungs- / Verknüpfungs- / Testschleife häufig erheblich beschleunigen.

Nehmen Sie zum Beispiel aus Sicht der Paketverwaltung libGL. Ich habe ungefähr ein Dutzend verschiedene Implementierungen davon in meinem Paketmanager, einige generische und einige zielgerichtete Grafikkarten. Wenn es nicht dynamisch verknüpft wäre, müsste es ein Dutzend Versionen jedes Programms geben, das mit libGL verknüpft ist, oder Sie müssten eine zusätzliche Abstraktionsebene entwickeln, die nicht so effizient ist wie ein Funktionsaufruf.

Denken Sie an ein Sicherheitsproblem in einer beliebten Bibliothek wie Qt. Mit der dynamischen Verknüpfung kann ich nur dieses eine Paket aktualisieren, anstatt jedes einzelne Paket, das in Qt verknüpft ist, identifizieren, neu kompilieren und bereitstellen zu müssen.

Statische Verknüpfungen können in unabhängig bereitgestellten Closed-Source-Anwendungen Vorteile haben, aber in der Open-Source-Paketverwaltung tut es mehr weh als hilft.

Karl Bielefeldt
quelle
2
Dies ist wahr (beschleunigt die Entwicklung), aber es ist wirklich frustrierend, dass es in die Produktion kommt. Das kanonische Beispiel ist Firefox. Der technische Aufwand (in Form von abscheulichen Hacks), mit dem die Auflösung dynamischer Verknüpfungssymbole beschleunigt wurde, sodass Firefox in angemessener Zeit geladen wird, ist absolut verrückt. Eine viel bessere Leistung hätte mit viel geringeren Engineering-Kosten erzielt werden können, wenn sie nur bereit gewesen wären, den gesamten projektinternen Code statisch zu verknüpfen (und auf Wunsch weiterhin dynamische Systembibliotheken und Plugins zu verknüpfen).
R .. GitHub STOP HELPING ICE
5

Freigegebene Bibliotheken werden von Linux- Distributionsbetreuern aus dem zweiten Grund stark bevorzugt . Für sie ist es sehr wichtig, dass jemand, der beispielsweise einen Sicherheitsfehler in zlib findet , nicht jedes einzelne Programm, das zlib verwendet, neu kompilieren muss - dies würde ihn nicht nur mehr CPU-Zyklen kosten Beim erneuten Kompilieren müsste dann jeder, der die Distribution verwendet, alle diese Programme erneut herunterladen . In der Zwischenzeit ist die Abhängigkeitshölle innerhalb der von einer Distribution bereitgestellten Pakete kein Problem, da alles getestet wurde, um mit diesen Bibliotheken zu funktionieren.

Wenn Sie Software von Drittanbietern erstellen , die Bibliotheken benötigt, die nicht in Ihrer Distribution enthalten sind, ist das statische Verknüpfen dieser Bibliotheken möglicherweise weniger problematisch als die Alternative, und das ist in Ordnung.

Die andere wichtige Sache zu wissen ist, dass sowohl GNU libcals auch GCC libstdc++Komponenten haben, die nicht zuverlässig funktionieren, wenn die Bibliothek statisch verknüpft ist. Das häufigste Problem ist dlopen, dass das Modul, mit dem Sie laden, dlopenselbst dynamisch verknüpft ist libc.so.6. Das bedeutet, dass Sie jetzt zwei Kopien der C-Bibliothek in Ihrem Adressraum haben, und es kommt zu Heiterkeit, wenn sie sich nicht einig sind, welche Kopie der internen mallocDatenstruktur (zum Beispiel) maßgeblich ist. Es kommt noch schlimmer: eine ganze Reihe von Funktionen , die scheinen zu haben nichts mit dem zu tun dlopen, wie gethostbynameund iconv, Verwendungdlopenintern (damit ihr Verhalten zur Laufzeit konfigurierbar ist). Glücklicherweise ist das ABI für libc und libstdc ++ sehr stabil, sodass es unwahrscheinlich ist, dass Sie auf Probleme stoßen, wenn Sie diese dynamisch verknüpfen.

zwol
quelle
2

Ich stimme dem letzten Punkt von mattnz zu: Diese Frage ist eine geladene Frage. Es wird davon ausgegangen, dass die statische Verknüpfung schlecht ist. Ich kann mir zwei Gründe vorstellen, warum dies nicht der Fall ist:

  • Statische Verknüpfungen sind sicher: Wenn eine gemeinsam genutzte Bibliothek so aktualisiert wird, dass eine Anwendung die neue verwendet (möglicherweise überschreibt die neue die alte oder die alte wird entfernt), kann das Risiko bestehen, dass die neue Version die Anwendung beschädigt. Dies ist eine Codeänderung außerhalb des Umfangs eines offiziellen Updates für die Anwendung. Es wurde möglicherweise nicht getestet. Die statische Verknüpfung umgeht dies, indem Bibliotheken nicht extern freigegeben werden. Ich bin der Meinung , dass dies aufgrund dieses Risikos ein Nachteil für gemeinsam genutzte Bibliotheken ist. Was ist, wenn eine neue Version einer gemeinsam genutzten Bibliothek einen neuen Fehler einführt, der bestimmte ältere Anwendungen beschädigt?

  • Durch statische Verknüpfung wird sichergestellt, dass eine Anwendung eigenständiger ist. Während gemeinsam genutzte Bibliotheken mit der primären ausführbaren Datei zusammengestellt werden können, werden sie häufig an gemeinsam genutzten Speicherorten abgelegt. Statisch verknüpfte Anwendungen lassen sich leichter als "portabel" im Sinne von "keine Änderungen an Dateien, Verzeichnissen oder Einstellungen des Betriebssystems erforderlich" (z. B. Windows-Verzeichnis, Registrierung usw.) sicherstellen.


quelle
Vielen Dank, dass Sie die Vorteile verbessert haben, die ich erwähnen wollte. Wenn Sie jedoch beispielsweise die meisten Pakete sehen, die von Linux-Distributionen bereitgestellt werden, werden sie nicht statisch kompiliert. Es ist offenbar , dass statische Kompilierung ist verpönt, zumindest von einer externen Sicht.
Florian Margaine
1
Dynamische Bibliotheken auf so ziemlich jedem Betriebssystem werden heutzutage nach Bedarf ausgelagert. Nur die tatsächlich verwendeten Seiten befinden sich im Speicher. Wenn mehrere Anwendungen dieselbe Funktionalität verwenden, teilen sie sich den Speicher und verwenden weniger als die statische Bibliothek. Wenn mehrere Apps unterschiedliche Funktionen in derselben Bibliothek verwenden, werden beide Funktionssätze ausgelagert, was ungefähr die gleichen Auswirkungen wie der statische Ansatz hat.
Alan Shutko
@AlanShutko Ich habe mich bemüht und diesen Teil auf verschiedene Weise neu getippt, weil Sie das erwähnt haben. In beiden Fällen gibt es keine wirklichen Garantien, selbst wenn moderne Betriebssysteme in der Praxis die Effizienz gemeinsam genutzter Bibliotheken mit dem Aufwand statischer Aufladung bieten. Ich werde wieder bearbeiten.
@Snowman Ich denke, der grundlegende Punkt ist, dass auf jedem realistischen Betriebssystem, das dynamische Verknüpfungen bereitstellt (ich kenne kein Betriebssystem, das dynamische Verknüpfungen verwendet, aber kein Paging erfordert), Ihr zweiter Punkt kein Wasser enthält: Speicher wird nicht tatsächlich verwendet es sei denn, die Funktion wird verwendet und der von einer dynamischen Bibliothek verwendete Speicher kann von verschiedenen Programmen, die sie verwenden, gemeinsam genutzt werden, wodurch die Speichernutzung für die dynamische Version effizienter und nicht geringer wird. Ihr erster und dritter Grund sind gültig, aber ich würde einfach den zweiten löschen: Mit realistischen Annahmen ist es einfach falsch.
Jules
@ Jules Ich stimme zu, es ist ein Punkt, der in modernen Betriebssystemen problematisch und von zweifelhafter Gültigkeit war. Ich habe es entfernt.
1

Statische und dynamische Bibliotheken haben jeweils ihre eigenen Verwendungszwecke. Wenn wir eine einzelne Anwendung im Umfang betrachten, erhalten wir eine andere Vorstellung davon, was notwendig ist und was nicht.

Die statische Verknüpfung vereinfacht die Anwendungsbereitstellung drastisch. Keine unterschiedlichen Versionen erkennen und damit umgehen müssen. Einfach backen und bereitstellen.

Der offensichtliche Vorteil dynamischer Bibliotheken ist die Möglichkeit, Aktualisierungen unabhängig anzuwenden.

Dies ist einer der Gründe, warum ich Maven und andere ähnliche Builder für dynamische Verknüpfungsprojekte für Java verabscheue. Sie erwarten, dass eine einzelne Bibliotheksversion für immer und ewig unter einer bestimmten URL verfügbar sein wird. Das Problem, das in 10 Jahren auftritt, wenn niemand die Anwendung kompilieren kann, weil alle Quellen und Gläser verschwunden sind, wird nicht verstanden.

viele Chips
quelle
Gibt es einen bestimmten Grund, warum es nicht möglich sein sollte, dass Programme, die FooLib1.8den Code für diese Bibliothek verwenden, auf standardmäßige Weise in ihr ausführbares Paket aufgenommen werden können, damit ein mitgeliefertes Upgrade-Dienstprogramm ein FooLib1.9Upgrade oder Downgrade durchführen kann? Die Art und Weise, wie Code in Classic Macintosh gespeichert wurde, hätte dies ziemlich einfach gemacht. Gibt es einen Grund, warum heutige Systeme dies nicht noch besser können sollten?
Supercat
@supercat meinst du, dass jede Version einer bestimmten Bibliothek auf dem System verfügbar wäre? Ich bin mir nicht sicher, ob ich die Frage verstehe. Die OP-Frage richtete sich eher auf systemweite gemeinsam genutzte Bibliotheken als auf statische Bibliotheken, die zusammen gepackt würden.
viele Chips
Mein Punkt war, dass ein ausführbares Paket, das alle benötigten Bibliotheken enthält, nicht die Möglichkeit ausschließen sollte, die darin enthaltenen Bibliotheken zu aktualisieren. Daher weiß ich nicht, dass ich die Möglichkeit, nach der Bereitstellung ein Upgrade durchzuführen, als Vorteil betrachten würde, wenn eine Anwendung nicht mit ihren Bibliotheken gebündelt wird.
Supercat
Wenn Sie mit der Lizenz einer bestimmten Bibliothek diese mit Ihrem Paket verteilen können, ist dies immer die bevorzugte Methode. Es reduziert die Anzahl der externen Abhängigkeiten. Da Sie alles verteilen würden, würde ein Upgrade- oder Patching-Mechanismus mit statischer oder dynamischer Methode genauso funktionieren. Patches basieren normalerweise auf binären Deltas. Es würde keinen Unterschied geben.
viele Chips