オンラインのほとんどのソースは、glibcを静的にリンクできると述べていますが、リンクしないようにしてください。例えば centosパッケージリポジトリ :
The glibc-static package contains the C library static libraries
for -static linking. You don't need these, unless you link statically,
which is highly discouraged.
これらの情報源は、なぜそれが悪い考えであるのかをめったに(または決して)言わない。
他の回答で示された理由は正しいですが、それらは最も重要な理由ではありません。
Glibcを静的にリンクしてはならない最も重要な理由は、NSS( Name Service Switch )モジュールをロードするために dlopen
を内部で広範囲に使用することですおよび iconv
変換。モジュール自体はCライブラリ関数を参照します。メインプログラムがCライブラリと動的にリンクされている場合は、問題ありません。しかし、メインプログラムがCライブラリと静的にリンクされている場合、dlopen
はCライブラリの2番目のコピーをロードして、モジュールの負荷要件。
つまり、「静的にリンクされた」プログラムでは、ファイルシステムにlibc.so.6
のコピーが必要であり、さらにNSSまたはiconv
またはその他のモジュール自体、およびモジュールに必要なその他の動的ライブラリが必要です。 、ld-linux.so.2
、libresolv.so.2
などのように。これは、プログラムを静的にリンクする場合に通常必要とされるものではありません。
また、静的にリンクされたプログラムには、アドレス空間にCライブラリの2つのコピーがあり、stdout
バッファーを使用する必要のある、0以外のsbrk
を呼び出そうとするユーザーと争う可能性があります。議論、そのようなこと。 glibc内には、これを機能させるための防御ロジックがたくさんありますが、機能することは保証されていません。
プログラムはgetaddrinfo
やiconv
を呼び出さないので、プログラムでこれを心配する必要はないと思うかもしれませんが、ロケールサポートは内部でiconv
を使用します。つまり、任意のstdio.h
関数がdlopen
の呼び出しをトリガーする可能性がありますが、これを制御するのではなく、ユーザーの環境変数設定がトリガーします。
Glibcのバグ修正は、アプリケーションを再ビルドしない限り、glibcをアップグレードしても静的にリンクされたアプリケーションには含まれません。
また、動的リンクを使用しない限り、 [〜#〜] nss [〜#〜] (ネームサービススイッチ)は機能しません。
Program/glibc
インターフェースは、POSIX、CおよびC++標準などによって標準化および文書化されています。たとえば、fopen()
関数はC標準に従って動作し、pthread_mutex_lock()
はPOSIXに従って動作します。
glibc
/kernelインターフェイスは標準化されていません。 fopen()
は内部でopen()
を使用していますか?それともopenat()
を使用しますか?または、他の何か?来年は何を使いますか?あなたは知りません。
glibc
/kernelインターフェースが変更されると、変更されたものを使用するが静的にglibc
をリンクするプログラムは動作しなくなります。
15年以上前、Solarisはこのまさに理由により、libc
のすべての静的バージョンを削除しました。
Solaris 10では、静的実行可能ファイルを構築できなくなりました。 ld(1)が静的リンクやアーカイブの使用を許可していないのではなく、libc.so.1のアーカイブバージョンであるlibc.aが提供されなくなっただけです。このライブラリは、ユーザーランドとカーネル間のインターフェースを提供します。このライブラリがないと、アプリケーションの形式を作成するのがかなり難しくなります。
私たちはしばらくの間、静的リンクに対してユーザーに警告してきましたが、libc.aに対するリンクは特に問題がありました。 solarisのすべてのリリースまたは更新(一部のパッチでさえ)により、libc.aに対してビルドされた一部のアプリケーションが失敗しました。問題は、libcがユーザーとカーネルの境界、つまりリリースごとに変更される可能性のある境界からアプリケーションを分離することになっていることです。
アプリケーションがlibc.aに対してビルドされている場合、そのアプリケーションが参照するカーネルインターフェイスはアーカイブから抽出され、アプリケーションの一部になります。したがって、このアプリケーションは、使用されているカーネルインターフェイスと同期しているカーネルでのみ実行できます。これらのインターフェースが変更された場合、アプリケーションは不安定な地面を踏んでいます。
...
編集:
Linuxカーネルインターフェースの安定性は、過大評価されているようです。詳細は LinuxカーネルAPIの変更/追加 を参照してください。要約する: