はじめに
プログラムが動けばそれでよい、ではなく、その内部で何が起きているのかを理解することが重要だと考え、本書を手に取りました。
本記事では、第8章「ソース・ファイルから実行可能ファイルができるまで」についてピックアップし、自分なりに整理しながらまとめていきます。
ソースファイルから実行可能ファイルができるまで
私たちが書いたソースコードは、そのままではCPUに理解されません。
そのため、コンパイルやリンクといった複数のステップを踏むことで、最終的に実行可能ファイルとなります。
ここでは、その過程に関わる主な5つの構成要素について見ていきます。
ソースファイル
プログラマが記述する、実行したいことを書いたファイルです。
このソースファイルは、コンパイラによってオブジェクトファイルに変換されます。
オブジェクトファイルはまだ単体では動作せず、必要なライブラリや他のオブジェクトファイルと一緒にリンクされて初めて実行可能ファイルとなります。
スタートアップ
実行可能ファイルに含まれる、プログラム実行時の開始時に呼び出される初期化用のコードです。
例えば、メモリの初期化やグローバル変数の設定などの初期化処理を行います。
スタティックリンクライブラリ
ビルド時に実行可能ファイルへ直接組み込まれるライブラリで、実行可能ファイルだけで動作可能です。
ダイナミックリンクライブラリ
プログラム実行時に読み込まれる外部ライブラリで、DLLファイルが必要になります。
インポートライブラリ
ダイナミックリンクライブラリを使用する際に、リンク時に必要となる参照情報を含んだファイルです。
スタティックリンクライブラリ vs ダイナミックリンクライブラリ
同じライブラリを使う場合でも、実行可能ファイルへの組み込み方によって、スタティックリンクライブラリとダイナミックリンクライブラリに分かれます。
以下の表は、主な違いを示しています。
観点 | スタティックリンク | ダイナミックリンク |
---|---|---|
実行可能ファイルのサイズ | 大きくなる | 小さくなる |
実行時の依存関係 | 少ない | 多い(DLLが必要) |
配布のしやすさ | 単体で完結 | DLLも一緒に配布が必要 |
ライブラリ更新時の影響 | 再ビルドが必要 | DLL差し替えで済む |
メモリ使用効率 | プログラムごとにコピー | ライブラリ共有可能 |
実際のコードと構成要素の対応関係
以下の簡単なC言語プログラムを例に、各構成要素がどのように関わっているかを整理してみます。
#include <stdio.h>
#include <windows.h>
int main() {
char buf[100];
sprintf(buf, "数値: %d", 42); // スタティックリンクライブラリの例
MessageBox(NULL, buf, "サンプルプログラム", MB_OK); // ダイナミックリンクライブラリの例
return 0;
}
-
ソースファイル
このC言語ファイルそのものがソースファイルにあたります。 -
スタートアップ
コンパイル時やプログラム中に明示的に書くものではなく、ビルド時に自動で組み込まれます。 -
スタティックリンクライブラリ
sprintf(buf, "数値: %d", 42);
の部分が該当します。
cw32.lib
というスタティックリンクライブラリに含まれており、ビルド時にこのライブラリから必要な機能が取り込まれて、実行可能ファイルに組み込まれます。 -
ダイナミックリンクライブラリ
MessageBox(NULL, buf, "サンプルプログラム", MB_OK);
の部分が該当します。
これはuser32.dll
に含まれている関数で、プログラム実行時にこの外部DLLから機能が読み込まれて使用されます。 -
インポートライブラリ
MessageBox()
を使うために、リンク時にimport32.lib
というインポートライブラリが使われます。
このライブラリはuser32.dll
に含まれる関数への参照情報を持っており、ビルド時に必要になります。
ソースコードには明示的には登場しません。
感想
- これまで名前だけ聞いたことがあったリンクや、普段目にしていた DLL ファイルの役割について、具体的に理解できてよかったです
- スタティックリンクライブラリとダイナミックリンクライブラリについては、それぞれにメリット・デメリットがあるため、用途や配布方法に応じて使い分けることが重要だとわかりました