リンカ(Linker)とは何か?– C言語で学ぶコンパイルの最終工程
1. はじめに
C言語などのネイティブ言語で開発をしていると、ビルド工程で「リンクエラー」や「未定義のシンボル」などのワードに遭遇します。
これらはすべてリンカ(Linker)という仕組みに関係しています。
本記事では、「リンカとは何か?」という基本から、C言語の具体例を使って仕組みと役割を分かりやすく解説します。
2. リンカ(Linker)とは?
2.1 リンカの役割
リンカは、コンパイル後に生成されたオブジェクトファイル(.o)を結合し、実行ファイル(バイナリ)を生成するツールです。
役割は以下の通り:
- 複数ファイルのコードを1つにまとめる
- 関数や変数の参照を解決する
- ライブラリの関数(例:printf)とリンクする
2.2 ビルドの流れ
C言語でのビルドは以下の4段階です:
3. 実例で理解するリンカの動作
3.1 ソースファイルを分割
ファイル1:main.c
#include <stdio.h> void greet(); // 別ファイルの関数 int main() { greet(); return 0; }
ファイル2:greet.c
#include <stdio.h> void greet() { printf("Hello from greet.c!\n"); }
3.2 コンパイルしてオブジェクトファイルを生成
gcc -c main.c # → main.o gcc -c greet.c # → greet.o
ここで生成されるのは中間のバイナリ(.o)で、まだ実行できません。
3.3 リンクして実行ファイルを生成
gcc main.o greet.o -o hello
この段階でリンカが動作し、main.oからgreet関数を探してgreet.oと結びつける(リンク)ことで、完全な実行ファイルhello
が生成されます。
3.4 実行
./hello
Hello from greet.c!
4. リンクエラーの例とその原因
例1:未定義の関数
もし main.c
にある greet();
を定義せず、greet.o
もリンクしなかった場合:
gcc main.c -o hello
出力:
/usr/bin/ld: /tmp/ccXXXX.o: in function `main': main.c:(.text+0x5): undefined reference to `greet' collect2: error: ld returned 1 exit status
これは、リンカがgreetの実体を見つけられなかったことを意味します。
例2:重複定義(duplicate symbol)
同じ関数や変数を複数ファイルで定義してしまった場合にもリンカエラーが発生します。
5. 静的リンクと動的リンク
種類 | 概要 | 特徴 |
---|---|---|
静的リンク | 関数の本体を実行ファイルに埋め込む | 実行ファイルが大きいが単体で動作 |
動的リンク | 実行時に共有ライブラリを参照(.so, .dll) | 実行ファイルが軽く、再利用性高い |
動的リンクの確認(Linux)
ldd ./hello
出力例:
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f...)
6. リンカに関する用語
- シンボル(symbol):関数名や変数名の識別子。リンク対象。
- 外部シンボル(undefined):他のファイルに定義されたもの。
- 解決(resolve):参照元と定義元を正しく結びつけること。
- 再配置(relocation):アドレスを正しい場所に調整する処理。
7. まとめ
項目 | 説明 |
---|---|
リンカとは? | オブジェクトファイルを結合し、実行可能ファイルを作る |
主な機能 | 参照解決、アドレス調整、ライブラリ接続 |
典型的エラー | 未定義関数、重複定義、ライブラリ忘れ |
使用コマンド | gcc -c , gcc *.o -o でコンパイルとリンクを分離 |
リンカの理解は、エラーの解決力とパフォーマンス意識を高める第一歩です。
とくにC/C++のような低レイヤー言語を扱うなら、リンカの仕組みを知っておくことで「なぜ動かないのか」を論理的に説明できるようになります。
参考リンク
- GNU Linker (ld) マニュアル
- C言語のビルドの流れ
- [Linux Programming Interface - リンカと実行ファイル構造]
参考書籍
リンク
リンク