静的リンクと動的リンクの違い:ライブラリの結合方法を比較

リンクは、コンパイルしたコードを、それが使うライブラリのコードと結び付ける作業です。静的リンクでは、必要なライブラリのコードをビルド時に実行ファイルへコピーするので、プログラムだけで完結します。動的リンクでは、実行ファイルは必要な共有ライブラリを記録するだけで、プログラムの起動時にOSがそれらを読み込むので、多くのプログラムが1つのコピーを共有できます。静的は配布が簡単で、動的はメモリを節約でき、更新もしやすくなります。

項目静的リンク動的リンク
いつ行うかビルド時。ライブラリのコードを実行ファイルにコピーするロード時や実行時。動的リンカーが共有ライブラリ(.so、.dll)を探してマップする
実行ファイルの大きさ大きい小さい
メモリの使用量各プログラムが、ライブラリのコードのコピーを持つ共有ライブラリの1つのコピーを、多くのプロセスで共有できる
更新とセキュリティの修正プログラムを作り直して配り直す必要があるライブラリを1回更新すれば、作り直さなくても効果が出る(インターフェースに互換性があれば)
起動時間やや速いやや遅い。シンボルの解決が必要(遅延させることが多い)
配布自己完結。ライブラリがインストールされていなくても動く対象のシステムに正しいバージョンのライブラリが必要。なければ起動に失敗する
実行時のコストプログラム全体の最適化と直接の呼び出しができるGOTやPLTを通る間接呼び出しで、わずかな負荷がある
バージョンの問題実行時にはないプログラムと、インストールされたライブラリの不一致が起こりうる
主な用途組み込みのファームウェア、単一ファイルのツール、最小構成のコンテナ汎用OS上のほとんどのプログラム、プラグイン、libcなどのシステムのライブラリ

数値は代表的な目安で、世代や製品によって異なります。

どんなときに使うか

静的
どこでも動く、自己完結したバイナリが欲しいとき。または、組み込みのファームウェアのように、OSのローダーがないとき。
動的
多くのプログラムが同じライブラリを共有し、メモリを節約して、ライブラリをまとめて修正したいとき。

よくある質問

プログラムがライブラリが見つからないというエラーで起動しないのはなぜですか?

動的リンクされていて、必要な共有ライブラリ(.soや.dllのファイル)が、そのコンピュータにインストールされていないからです。ライブラリをインストールするか、静的リンクにします。

動的リンクはメモリを節約できますか?

はい。共有ライブラリの1つのコピーを、多くのプロセスで共有できます。

静的リンクのほうが速いですか?

わずかに速いです。起動時のシンボルの解決や、GOTとPLTを通る間接呼び出しがなく、プログラム全体の最適化もできます。

なぜ動的リンクはセキュリティの更新に役立つのですか?

共有ライブラリを1回修正すれば、それを使うすべてのプログラムが、作り直さなくても、その恩恵を受けられるからです。

理解度チェック

静的リンクの説明として正しいものはどれか。

  1. A使うライブラリのコードを実行ファイルの中にコピーして結合する
  2. Bプログラムを実行するたびに、ライブラリを読み込んで結合する
  3. Cライブラリを使わずに、すべての処理を1つのソースファイルに書く
答えと解説を見る

正解:A. 使うライブラリのコードを実行ファイルの中にコピーして結合する

静的リンクでは、リンカが静的ライブラリ(Linuxでは.aファイル)から必要な関数を取り出して実行ファイルに組み込みます。実行環境にライブラリがなくても動き、起動時の結合の手間もありませんが、実行ファイルが大きくなり、同じライブラリを使うプログラムごとにコピーを持ちます。ライブラリに不具合の修正があっても、作り直さないと反映されません。

動的リンク(共有ライブラリ)の利点として正しいものはどれか。

  1. A実行環境にライブラリがなくても、必ず動く
  2. B複数のプログラムが1つのライブラリをメモリ上で共有でき、ライブラリを更新すれば作り直さずに修正が反映される
  3. C起動時の処理がまったく不要になり、静的リンクより必ず速く起動する
答えと解説を見る

正解:B. 複数のプログラムが1つのライブラリをメモリ上で共有でき、ライブラリを更新すれば作り直さずに修正が反映される

動的リンクでは、実行ファイルには「どの共有ライブラリのどの関数を使うか」だけを記録し、実行時に動的リンカがライブラリを読み込んで結びつけます。共有ライブラリのコードは書き換えないので、物理メモリ上の1つのコピーを多くのプロセスで共有できます。不具合や脆弱性の修正もライブラリを差し替えるだけで済みます。ただし起動時に結合の手間がかかります。

動的リンクを使ったプログラムを別のコンピュータにコピーして実行したら、起動しなかった。最も考えられる原因はどれか。

  1. A実行ファイルの中にライブラリのコードがすべて入っていて、大きすぎたから
  2. B動的リンクのプログラムは、作ったコンピュータでしか動かない決まりだから
  3. C必要な共有ライブラリが入っていないか、互換性のないバージョンしかない
答えと解説を見る

正解:C. 必要な共有ライブラリが入っていないか、互換性のないバージョンしかない

動的リンクのプログラムは、実行するコンピュータにある共有ライブラリを使います。必要なライブラリがない、または関数が足りない古いバージョンしかないと、動的リンカが結合できず起動に失敗します。Linuxではlddコマンドで、プログラムが必要とする共有ライブラリと、それが見つかるかどうかを確かめられます。配布しやすさを重視して、あえて静的リンクにすることもあります。

  1. 静的ライブラリ(.aファイル)と一緒にリンクするとき、リンカが実行ファイルに組み込むものとして正しいものはどれか。
  2. 共有ライブラリで使われるGOT(グローバルオフセットテーブル)の役割として正しいものはどれか。
  3. 100個のプロセスが同じ共有ライブラリを使っているとき、物理メモリの使い方として正しいものはどれか。

リンカ・ローダと実行形式の練習問題へ

関連する用語の解説

静的リンク
使うライブラリのコードを実行ファイルの中にコピーして結合する方式。実行環境にライブラリがなくても動くが、ファイルが大きくなり、ライブラリの修正は作り直さないと反映されない。
動的リンク
実行時に共有ライブラリを読み込んで結びつける方式。ライブラリをプロセス間で共有でき、差し替えで修正が反映されるが、実行環境に合うライブラリが必要。
共有ライブラリ
動的リンクで実行時に読み込まれるライブラリ。Linuxでは.so、Windowsでは.dll。位置独立コードで作られ、コードのページを多くのプロセスで共有できる。
静的ライブラリ
多くのオブジェクトファイルを1つにまとめたアーカイブ(Linuxでは.a)。静的リンクのとき、リンカは必要なオブジェクトだけを取り出して実行ファイルに組み込む。

関連する比較