1. ホーム
  2. c++

[解決済み] ライブラリパスの優先順位を指定するには?

2022-11-17 15:33:33

質問

c++のプログラムを g++ld . 私が持っているのは .so ライブラリがあり、リンク時に使用したい。しかし、同じ名前のライブラリが /usr/local/lib に存在し、かつ ld は、私が直接指定しているライブラリではなく、そのライブラリを選択します。どのように私はこれを修正することができますか?

以下の例では、私のライブラリファイルは /my/dir/libfoo.so.0 . 私が試した中でうまくいかないこと。

  • 私の g++ コマンドは g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • 追加 /my/dir の最初か最後に $PATH en` 変数
  • 追加 /my/dir/libfoo.so.0 をg++の引数として追加しました。

どのように解決するのですか?

新しいライブラリがある場所のパスを LD_LIBRARY_PATH (Macでは少し違う名前になります ...)

あなたの解決策は -L/my/dir -lfoo オプションを使用し、実行時に LD_LIBRARY_PATH を使用してライブラリの場所を指定します。

LD_LIBRARY_PATHの使用には注意が必要です。 - を短くする(リンクより)。

...意味合い..:

セキュリティ : LD_LIBRARY_PATH で指定されたディレクトリは、標準の場所より先に(!)検索されることを覚えていますか?そうすると そのため、悪意のある人があなたのアプリケーションに、悪意のあるコードを含む共有ライブラリのバージョンを読み込ませることができるのです。 悪意のあるコードを含む共有ライブラリのバージョンを読み込ませることができるのです! これが setuid/setgid 実行形式がこの変数を無視する理由のひとつです!

パフォーマンス : リンクローダーは、共有ライブラリが存在するディレクトリを見つけるまで、指定されたすべてのディレクトリを検索する必要があります。 が存在するディレクトリを見つけるまで、リンクローダーは指定されたすべてのディレクトリを検索する必要があります - アプリケーションがリンクされているすべての共有ライブラリに対して! これは、open()への多くのシステムコールを意味します。 「ENOENT (No such file or directory)" で失敗します! パスが多くのディレクトリを含んでいる場合 ディレクトリが多数存在する場合、失敗する呼び出しの数は直線的に増加します。 アプリケーションの起動時間を見れば、それがわかるでしょう。もし、いくつかの (ディレクトリの一部(またはすべて)がNFS環境である場合、アプリケーションの起動時間 アプリケーションの起動時間が長くなり、システム全体が遅くなる可能性があります。 システム全体が遅くなります!

不整合 : これは最も一般的な問題です。LD_LIBRARY_PATH はアプリケーションに、リンクされていない共有ライブラリをロードするよう強制します。 アプリケーションに強制的にロードさせます。 バージョンと互換性がない可能性が高いです。これは、非常に明白で、例えば、アプリケーションがクラッシュすることもあれば これは、アプリケーションがクラッシュするなど、非常に明白な場合もあれば、ピックアップされたライブラリが元のバージョンと互換性がない場合、間違った結果につながる場合もあります。 このような場合、アプリケーションがクラッシュしたり、あるいは、拾ったライブラリが元のバージョンと全く同じように動作しないため、誤った結果を招く可能性があります。特に 後者はデバッグが困難な場合があります。

または

gccからリンカにrpathオプションを使用 - ランタイムライブラリ検索パスが使用されます。 標準のディレクトリを探すのではなく、ランタイムライブラリの検索パスを使用します (gcc オプション)。

-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)

これは一時的な解決策としては良い方法です。リンカは標準のディレクトリを調べる前に、まず LD_LIBRARY_PATH を検索してライブラリを探します。

LD_LIBRARY_PATH を恒久的に更新したくない場合は、コマンドラインでその場で更新することができます。

LD_LIBRARY_PATH=/some/custom/dir ./fooo

リンカがどのようなライブラリを知っているかは、(例)を使って確認することができます。

/sbin/ldconfig -p | grep libpthread
        libpthread.so.0 (libc6, OS ABI: Linux 2.6.4) => /lib/libpthread.so.0

そして、アプリケーションがどのライブラリを使用しているかを確認することができます。

ldd foo
        linux-gate.so.1 =>  (0xffffe000)
        libpthread.so.0 => /lib/libpthread.so.0 (0xb7f9e000)
        libxml2.so.2 => /usr/lib/libxml2.so.2 (0xb7e6e000)
        librt.so.1 => /lib/librt.so.1 (0xb7e65000)
        libm.so.6 => /lib/libm.so.6 (0xb7d5b000)
        libc.so.6 => /lib/libc.so.6 (0xb7c2e000)
        /lib/ld-linux.so.2 (0xb7fc7000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7c2a000)
        libz.so.1 => /lib/libz.so.1 (0xb7c18000)