Warum muss ich jedes Mal, wenn ich meine Anwendung ausführe, LD_LIBRARY_PATH mit einem Export definieren?

Lesezeit: 5 Minuten

Benutzeravatar von Paul Wicks
Paul Wick

Ich habe Code, der einige gemeinsam genutzte Bibliotheken verwendet (C-Code auf gcc). Beim Kompilieren muss ich die Include- und Bibliotheksverzeichnisse explizit mit -I und -L definieren, da sie nicht an den Standardorten liegen. Wenn ich versuche, den Code auszuführen, erhalte ich die folgende Fehlermeldung:

./sync_test 
./sync_test: error while loading shared libraries: libsync.so: cannot open shared object file: No such file or directory

Gehen Sie jedoch wie folgt vor, alles funktioniert einwandfrei:

export LD_LIBRARY_PATH="/path/to/library/"
./sync_test

Nun, das Merkwürdige daran ist, dass dies nur einmal funktioniert. Wenn ich versuche, sync_test erneut auszuführen, erhalte ich denselben Fehler, es sei denn, ich führe zuerst den Exportbefehl aus. Ich habe versucht, meiner .bashrc Folgendes hinzuzufügen, aber es hat keinen Unterschied gemacht:

LD_LIBRARY_PATH="/path/to/library/"

  • Ich denke, all diese Vorschläge sind schlecht – eindeutig ein Fehler mit Linux. Warum wird L-Pfad zur Kompilierungszeit nicht an die Laufzeit übergeben?

    Benutzer1129143

    4. Januar 2012 um 4:00 Uhr

  • Sie können einen Pfad mit festlegen -rpathaber dies ist normalerweise nicht wünschenswert, da es diesen Pfad dann anderen Systemen aufzwingt – siehe zweiter Kommentar zu stackoverflow.com/a/695539/168175

    – Flexo

    4. Januar 2012 um 4:24 Uhr


Benutzeravatar von sigjuice
Sigisaft

Sie sollten das Setzen vermeiden LD_LIBRARY_PATH in deiner .bashrc. Sehen Why LD_LIBRARY_PATH is bad für mehr Informationen.

Verwenden Sie die Linker-Option -rPfad beim Verlinken, damit der dynamische Linker weiß, wo er zu finden ist libsync.so während der Laufzeit.

gcc ... -Wl,-rpath /path/to/library -L/path/to/library -lsync -o sync_test

BEARBEITEN:

Eine andere Möglichkeit wäre, einen Wrapper wie diesen zu verwenden

#!/bin/bash

LD_LIBRARY_PATH=/path/to/library sync_test "$@"

Wenn sync_test andere Programme startet, verwenden sie möglicherweise die Bibliotheken in /path/to/library was beabsichtigt sein kann oder nicht.

  • Das hilft wirklich nicht, wenn Sie die Anwendung auf den Computer einer anderen Person verschieben und diese die Bibliothek nicht in den gleichen /Pfad/zu legen möchte, den Sie zum Zeitpunkt der Verknüpfung erwartet haben. Während -rpath für Systemadministratoren und Distributionsanbieter sicherlich nützlich ist, halte ich es für vermessen, dies von einer Einzelperson festzulegen.

    – Tom

    30. März 2009 um 3:56 Uhr

  • Obwohl, Ihrer ersten Aussage “Vermeiden Sie das Setzen von LD_LIBRARY_PATH in Ihrer .bashrc” stimme ich zu 100% zu. Eine Mittelwegslösung, die ich verwendet habe, ist ein Bash-Skript $HOME/bin/myprogram, das den lokalen LD_LIBRARY_PATH festlegt und dann /path/to/real/myprogram ausführt.

    – Tom

    30. März 2009 um 3:58 Uhr

  • Sie haben Recht. Man kann nicht annehmen, wo jemand seine Bibliotheken haben will. Falls es eine feste Beziehung zwischen bin/ und lib/ gibt, könnte etwas wie -rpath $ORIGIN/../lib angemessener sein. Es gibt auch ein Programm namens chrpath, das den rpath in ausführbaren ELF-Dateien ändern kann.

    – Sigissaft

    30. März 2009 um 6:32 Uhr

  • Ich stimme der Verwendung eines Wrapper-Shell-Skripts zu. Ich werde meine Antwort aktualisieren.

    – Sigissaft

    30. März 2009 um 6:35 Uhr

  • Danke für den Tipp. Keines der im Artikel erwähnten Dinge ist in meinem Fall wirklich ein Problem (dieser Code wird von mir immer nur auf einem Computer ausgeführt), aber ich werde sie auf jeden Fall berücksichtigen, wenn ich jemals auf ein ähnliches Problem stoße.

    – Paul Wick

    31. März 2009 um 4:20 Uhr

Benutzeravatar von brian-brazil
Brian-Brasilien

Verwenden

export LD_LIBRARY_PATH="/path/to/library/"

in Ihrer .bashrc andernfalls ist es nur für Bash verfügbar und nicht für Programme, die Sie starten.

Versuchen -R/path/to/library/ -Flag, wenn Sie verlinken, wird das Programm in diesem Verzeichnis suchen und Sie müssen keine Umgebungsvariablen setzen.

EDIT: Sieht so aus -R ist nur Solaris, und Sie verwenden Linux.

Eine alternative Möglichkeit wäre, den Pfad zu hinzuzufügen /etc/ld.so.conf und Renn ldconfig. Beachten Sie, dass dies eine globale Änderung ist, die für alle dynamisch verknüpften Binärdateien gilt.

  • Verwenden -Wl,-rpath (bei Weitergabe an cc) oder -rpath (bei Weitergabe an ld) als tragbarer als -R.

    – vergänglich

    30. März 2009 um 17:35 Uhr

  • -rpath kann problematisch sein, siehe wiki.debian.org/RpathIssue für eine Diskussion

    – Flexo

    4. Januar 2012 um 4:27 Uhr

  • Aus Kompatibilitätsgründen wird -R auch von GNU ld unterstützt, obwohl dies, wie im Kommentar von @awoodland erwähnt, unerwünscht ist. (“Top 10 kommerzieller Softwarefehler” sogar, würde ich sagen)

    – Jörgensen

    4. Januar 2012 um 5:21 Uhr

Sie können das alles einfach in eine Zeile schreiben:

LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/path/to/library" ./sync_test

Sollte die Sache etwas einfacher machen, auch wenn es nichts Grundlegendes ändert

  • Diese Syntax ist wunderbar … besonders wenn ein Teil Ihres Programmverhaltens auf vorübergehenden Umgebungsvariablen wie TMP oder TMPDIR basiert

    – Tom

    30. März 2009 um 0:12 Uhr

Haben Sie in Ihre .bashrc ‘exportiert’?

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"/path/to/library"

Anstatt den Bibliothekssuchpfad zur Laufzeit mit LD_LIBRARY_PATH zu überschreiben, könnten Sie ihn stattdessen mit in die Binärdatei selbst backen rpath. Wenn Sie mit GCC verknüpfen, fügen Sie hinzu -Wl,-rpath,<libdir> sollte den Trick machen, wenn Sie mit ld verlinken, ist es nur -rpath <libdir>.

Benutzeravatar von Roalt
Roalt

Was Sie auch tun können, wenn Sie es auf Ihrem System installiert haben, ist, das Verzeichnis, das die gemeinsam genutzten Bibliotheken enthält, zu Ihrem hinzuzufügen /etc/ld.so.conf Datei oder erstellen Sie eine neue Datei in /etc/ld.so.conf.d/

(Ich habe sowohl die RHEL5- als auch die Ubuntu-Distribution überprüft, daher denke ich, dass sie für Linux generisch ist.)

Das Programm ldconfig stellt sicher, dass sie systemweit eingebunden werden.

Weitere Informationen finden Sie unter folgendem Link:
www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/dlls.html

Benutzeravatar von Rick Smith
Rick Smith

Sie könnten in Ihrem Code ein Anrufsystem mit der neuen Definition hinzufügen:

sprintf(newdef,"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%s:%s",ld1,ld2);
system(newdef);

Aber ich weiß nicht, dass es die richtige Lösung ist, aber es funktioniert.

Grüße

1408140cookie-checkWarum muss ich jedes Mal, wenn ich meine Anwendung ausführe, LD_LIBRARY_PATH mit einem Export definieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy