リンク基本事項

コンパイルした後にオブジェクトファイルをリンクして実行ファイルを作成するという作業を一般にリンクと呼ぶが、そのリンクについての理解が曖昧なので今回まとめてみることにした。

まずリンクの種類として、スタティック(静的)リンクとダイナミック(動的)リンクの二つがある。それぞれについて説明する。

スタティックリンク

オブジェクトファイルをライブラリ中のルーチンとリンクする際、そのルーチンも実行ファイルに含めてしまうことである。このため、ファイルサイズはダイナミックリンク時よりも大きくなる。静的ライブラリは基本的には、.aという拡張子であることが多い。

ダイナミックリンク

リンク時には、オブジェクトファイルが実行時にライブラリ中のルーチンと結合できるように設定ファイルに書き込むだけで、実行ファイルに含めるようなことはしない。そのルーチンを使う時になって初めてそれをメモリ上にロードするので、メモリの節約になる。このため、実行ファイルサイズはスタティックリンク時よりも小さい。動的ライブラリは基本的には、.soという拡張子であることが多い。

ファイルサイズの比較

スタティックリンクの方がファイルサイズが大きくなることがわかっているので、それを確かめてみる。まずは以下のような標準ライブラリを呼び出すような簡単なHello, Worldコードを想定する。

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

まずは、以下のコマンドでコンパイルとリンクしてみる。オプションをつけずにリンクするとダイナミックリンクとなる。

$ cc -o hello.dynamic hello.c

-vオプションをつけて上のコマンドを実行すると、-L/usr/local/libとなっており、ここのライブラリを参照してリンクしていることがわかる。

次にスタティックリンクをしてみる。-staticオプションを付けるとできるらしいので、やってみた。すると以下のようなエラーが出た。

$ cc -static -o hello.static hello.c
ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)

どうやら-Lというオプションで、printtfのライブラリが入っているパスを指定する必要があるらしい。しかし、どこにprintfのライブラリがあるのか。。。printfのダイナミックリンクライブラリはあるかもしれないが、もしかしたらprintfのスタティックライブラリはない?

以下にリンクを勉強する上で参考になりそうなサイトを載せておく。これらを参考にまたリンクについて勉強してみようと思う。

参照