元の C ランタイム ライブラリは、複数のモジュールから構築されたプログラムをサポートする必要があるとは想定されていませんでした。これには、およびのような暗黙的なグローバル状態を持つ関数errno
およびのようなグローバル変数が含まれています。DLL を CRT の独自のコピーにリンクすることはできますが、DLL インターフェイスの設計方法に関してかなり厳しい要件が課せられます。CRT の状態に依存しないように十分に注意する必要があります。これを間違えると、実行時の誤動作を診断することがほとんど不可能になります。stdout
strtok()
malloc()
これを回避するには、プロセス内に CRT のコピーを1 つだけ配置します。これが /MD の目的であり、DLL に格納されている CRT のバージョンに依存することになります。すべてのモジュールで共有されます。VS2013 で使用される msvcr120.dll と同様です。
コンパイラは、その DLL バージョンを適切に使用できるように、これを認識する必要があります。簡単な例はerrno
、/MT を使用したグローバル変数ですが、/MD を使用して関数呼び出しにマクロ化されているため、DLL 内の 1 つのグローバルのみが最後の既知の値を追跡するために使用されます。/MD が有効な場合、_DLL
マクロが定義され、コンパイラの .h ファイルで使用されます。
もう 1 つの副作用は、コンパイラが msvcrt.lib または libcmt.lib のリンク ディレクティブ (#pragma コメントと同等) を自動的に挿入することです。間違いを回避し、CRT ライブラリへのリンク指示を明示的に与える必要がないように設計されています。間違えると、リンカのエラー メッセージを診断するのが非常に難しくなります。/MT と /MD の不一致でビルドされた .obj または .lib ファイルをリンクしようとしたときに得られる種類と同じです。もちろん、どちらも適切に機能しません。両方に依存することはできません。
どの .libs もインポート ライブラリではありません
名前でリストしたもの、ole32.lib、advapi32.lib、user32.lib は、実際にはインポート ライブラリです。これらは、標準のオペレーティング システム DLL です。実行時に、プログラムは対応する DLL をロードし、デバッガーから簡単に確認できます。VS の場合、これは [出力] ウィンドウに表示されます。これらの DLL は、実際にはプログラムとは異なる CRT を使用しており、c:\windows\system32\msvcrt.dll にバインドされていることに注意してください。winapi は、これが問題にならないように慎重に設計されています。
リンクはデフォルトで静的リンクまたは動的リンクを使用しますか
デフォルトはありません。リンクする .lib によって異なります。静的リンク ライブラリとインポート ライブラリを区別します。DLL をビルドすると、インポート ライブラリが作成されます。コードを含まない小さなファイルで、DLL 内のエクスポートされた関数の名前のみを含むため、リンカはプログラムのインポート テーブルにエントリを配置することを認識します。DLL の依存関係が解決され、インポートされた関数は、プログラムの開始時にローダーによってバインドされます。