GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Statisches Linken von libstdc++:Irgendwelche Fallstricke?

Möglicherweise müssen Sie auch sicherstellen, dass Sie nicht von der dynamischen glibc abhängig sind. Führen Sie ldd aus auf Ihrer resultierenden ausführbaren Datei und beachten Sie alle dynamischen Abhängigkeiten (libc/libm/libpthread sind übliche Verdächtige).

Eine zusätzliche Übung wäre das Erstellen einer Reihe von beteiligten C++11-Beispielen mit dieser Methodik und das tatsächliche Ausprobieren der resultierenden Binärdateien auf einem echten 10.04-System. In den meisten Fällen wissen Sie sofort, ob das Programm funktioniert oder abstürzt, es sei denn, Sie machen beim dynamischen Laden etwas Seltsames.


Dieser Blogpost ist ziemlich ungenau.

Soweit ich weiß, wurden C++-ABI-Änderungen mit jeder größeren Version von GCC eingeführt (d. h. diejenigen mit unterschiedlichen Komponenten der ersten oder zweiten Versionsnummer).

Nicht wahr. Die einzigen C++-ABI-Änderungen, die seit GCC 3.4 eingeführt wurden, waren abwärtskompatibel, was bedeutet, dass die C++-ABI seit fast neun Jahren stabil ist.

Erschwerend kommt hinzu, dass die meisten großen Linux-Distributionen GCC-Snapshots verwenden und/oder ihre GCC-Versionen patchen, wodurch es praktisch unmöglich ist, genau zu wissen, mit welchen GCC-Versionen Sie es zu tun haben, wenn Sie Binärdateien verteilen.

Die Unterschiede zwischen den gepatchten GCC-Versionen der Distributionen sind geringfügig, und die ABI-Änderungen ändern sich nicht, z. Fedoras 4.6.3 20120306 (Red Hat 4.6.3-2) ist ABI-kompatibel mit den Upstream-Versionen von FSF 4.6.x und mit ziemlicher Sicherheit mit jedem 4.6.x einer anderen Distribution.

Unter GNU/Linux verwenden die Laufzeitbibliotheken von GCC die ELF-Symbolversionierung, sodass es einfach ist, die von Objekten und Bibliotheken benötigten Symbolversionen zu überprüfen, und ob Sie einen libstdc++.so haben die diese Symbole bereitstellt, wird es funktionieren, es spielt keine Rolle, ob es sich um eine etwas andere gepatchte Version als eine andere Version Ihrer Distribution handelt.

aber kein C++-Code (oder irgendein Code, der die C++-Laufzeitunterstützung verwendet) darf dynamisch gelinkt werden, wenn dies funktionieren soll.

Das ist auch nicht wahr.

Das heißt, statisch auf libstdc++.a verlinken ist eine Option für Sie.

Der Grund, warum es möglicherweise nicht funktioniert, wenn Sie eine Bibliothek dynamisch laden (mit dlopen ) ist, dass libstdc++-Symbole, von denen es abhängt, von Ihrer Anwendung möglicherweise nicht benötigt wurden, als Sie sie (statisch) verknüpft haben, sodass diese Symbole in Ihrer ausführbaren Datei nicht vorhanden sind. Dies kann gelöst werden, indem die gemeinsam genutzte Bibliothek dynamisch mit libstdc++.so verknüpft wird (was sowieso das Richtige ist, wenn es darauf ankommt.) Die Einfügung von ELF-Symbolen bedeutet, dass Symbole, die in Ihrer ausführbaren Datei vorhanden sind, von der gemeinsam genutzten Bibliothek verwendet werden, aber andere, die nicht in Ihrer ausführbaren Datei vorhanden sind, in welchem ​​\u200b\u200blibstdc++.so es verlinkt. Wenn Ihre Anwendung dlopen nicht verwendet Sie brauchen sich darum nicht zu kümmern.

Eine andere Option (und die, die ich bevorzuge) ist die Bereitstellung des neueren libstdc++.so neben Ihrer Anwendung und stellen Sie sicher, dass es vor dem Standardsystem libstdc++.so gefunden wird , was erreicht werden kann, indem der dynamische Linker gezwungen wird, an der richtigen Stelle zu suchen, entweder mit $LD_LIBRARY_PATH Umgebungsvariable zur Laufzeit oder durch Setzen eines RPATH in der ausführbaren Datei zur Verbindungszeit. Ich bevorzuge RPATH da es nicht darauf angewiesen ist, dass die Umgebung richtig eingestellt ist, damit die Anwendung funktioniert. Wenn Sie Ihre Bewerbung mit '-Wl,-rpath,$ORIGIN' verlinken (Beachten Sie die einfachen Anführungszeichen, um zu verhindern, dass die Shell versucht, $ORIGIN zu erweitern ), dann hat die ausführbare Datei einen RPATH von $ORIGIN Dadurch wird der dynamische Linker angewiesen, im selben Verzeichnis wie die ausführbare Datei selbst nach gemeinsam genutzten Bibliotheken zu suchen. Wenn Sie den neueren libstdc++.so setzen im selben Verzeichnis wie die ausführbare Datei wird es zur Laufzeit gefunden, Problem gelöst. (Eine andere Möglichkeit besteht darin, die ausführbare Datei in /some/path/bin/ zu platzieren und die neuere libstdc++.so in /some/path/lib/ und mit '-Wl,-rpath,$ORIGIN/../lib' verlinken oder an einem anderen festen Ort relativ zur ausführbaren Datei, und setzen Sie den RPATH relativ zu $ORIGIN )


Eine Ergänzung zu Jonathan Wakelys hervorragender Antwort, warum dlopen() problematisch ist:

Aufgrund des neuen Ausnahmebehandlungspools in GCC 5 (siehe PR 64535 und PR 65434) erhalten Sie jedes Mal ein Speicherleck (des Pool-Objekts), wenn Sie eine Bibliothek, die statisch mit libstdc++ verknüpft ist, öffnen und schließen. Wenn also die Möglichkeit besteht, dass Sie jemals dlopen verwenden, scheint es eine wirklich schlechte Idee zu sein, libstdc++ statisch zu linken. Beachten Sie, dass dies ein echtes Leck ist, im Gegensatz zu dem harmlosen, das in PR 65434 erwähnt wird.


Linux
  1. Appnativefy – Verwandeln Sie jede Website in ein einziges ausführbares Appimage

  2. Protokollieren Sie einen Befehl ähnlich wie "time"?

  3. Gibt es einen Unterschied zwischen ausführbaren Binärdateien zwischen Distributionen?

  4. Das statische Linken von Linux ist tot?

  5. C/C++ mit GCC:Ressourcendateien statisch zur ausführbaren Datei/Bibliothek hinzufügen

Wie man eine Datei unter Linux ausführbar macht

Wie leitet man Befehle an ein beliebiges Terminal weiter?

Nativefier – Verwandeln Sie jede Website ganz einfach in eine Desktop-Anwendung

Einbetten eines Symbols in eine ausführbare Linux-Datei

iconv jede Kodierung nach UTF-8

Ist X11 gefährlich?