EXEファイルの読み込み
EXEファイルには、対象システムのbit数、サブシステム(ウィンドウ、コンソール)、
プログラムのエントリポイントへのポインタ、
コード、データ、リソース、DLLの静的リンク情報などが保存されています。
プログラムのエントリポイントに名前はありません。
Visual C++を使う場合は、linkコマンドの/ENTRYオプションで与えたシンボルになります。
EXEファイルを引数としてCreateProcess()を呼び出すと、次の処理が行われます。
プロセスの作成
メモリ、ハンドルの確保
コードやデータの読み込み
1つのスレッドと、スレッド用データの確保
静的リンクされたDLLの読み込み
DLLへの通知
スレッドをエントリポイントから実行
実行中のスレッドがCreateThread()を呼び出すと、次の処理が行われます。
1つのスレッドと、スレッド用データの確保
DLLへの通知
スレッドをエントリポイントから実行
なお、32bit用のEXEファイルが64bit用のDLLファイルを直接リンクしたり、
64bit用のEXEファイルが32bit用のDLLファイルを直接リンクすることはできません。
DLLファイルの読み込み
DLLファイルの構造はEXEファイルとほとんど同じですが、
外部から呼び出せる関数などを表す公開シンボルが追加されています。
DLL自身も他のDLLをリンクできます。
DLLは静的リンクによりプロセスの起動時に読み込むことも、
LoadLibrary()とFreeLibrary()により、動的な読み込みと解放を行うこともできます。
DLLのエントリポイントは次の関数で、
プロセスおよびスレッドの開始と終了のたびに呼び出されます。
以下ではDllEntryPointと呼びます。
BOOL APIENTRY DllEntryPoint(
HANDLE hModule, DWORD dwReason, LPVOID pv);
hModule | DLLのモジュールハンドルを表します。キャストにより、HINSTANCEとしても利用できます。 |
dwReason | この関数が呼び出された理由を表します。 |
pv | dwReasonごとに決まる追加パラメータです。 |
dwReasonは次のいずれかになります。
DLL_PROCESS_ATTACH | プロセスの初期化。pvはプロセス開始時であればNULL以外、LoadLibrary()の場合はNULLになります。 |
DLL_PROCESS_DETACH | プロセスの終了処理。pvはプロセス終了時であればNULL以外、FreeLibrary()の場合はNULLになります。 |
DLL_THREAD_ATTACH | スレッドの初期化処理。 |
DLL_THREAD_DETACH | スレッドの終了処理。 |
LoadLibrary()によって後から読み込まれた場合も、すべてのプロセスとスレッドが初期化されます。
Visual C++ライブラリの初期化処理
Visual C++の場合、プログラムのエントリポイントは次のようになっています。
EXEファイル (ウィンドウ) | WinMainCRTStartup() |
EXEファイル (コンソール) | mainCRTStartup() |
DLLファイル | DllMainCRTStartup() |
WinMainCRTStartup()はC/C++ライブラリの初期化を行った後、
WinMain()関数を呼び出します。
mainCRTStartup()は呼び出す関数がmain()関数である点を除き、
WinMainCRTStartup()とほぼ同じです。
DllMainCRTStartup()はCライブラリやC++ライブラリの初期化を行った後、
DllMain()関数を呼び出します。DllMain()関数がない場合は空の関数として扱われます。
Visual C++はC/C++ライブラリのデータをスレッド単位でもっています。スレッドを作成し、そのスレッドでC/C++ライブラリを利用する場合は、CreateThread()の代わりに_beginthreadex()を呼び出す必要があります。
同一のC/C++ライブラリをEXEとDLLで共有したい場合には、DLL版のC/C++ライブラリを使う必要があります。例えばEXE内でnewやmalloc()により確保されたメモリをDLL内でdeleteやfree()により解放する場合は、DLL版のC/C++ライブラリが必要になります。
関連ページ
COM/ActiveXの解説ページ 目次
前の項目: プログラムの実行環境