1

3 ~ 4 個の外部ライブラリを使用する C ファイルがあります。cl.exeand link.exe(MSVC)を使用して構築されています。

ビルド スクリプトは、exe を生成するプロセスが 2 つの段階にあることを示しています。

  • cl.exeファイルを取得するには、「/c」オプションを使用し.oます。これには他にもたくさんのフラグが付けられていますが、私が関心を持っているのは/MD. MSDN は次のように述べています。

アプリケーションがランタイム ライブラリのマルチスレッド固有および DLL 固有のバージョンを使用するようにします。_MT と _DLL を定義し、コンパイラがライブラリ名 MSVCRT.lib を .obj ファイルに配置するようにします。

コンパイルするだけで、リンクしていない場合、/MDwithを与えることの用途は何ですか?cl

  • この後link.exe、exeを生成するために使用されます。リンク用にいくつかの.libファイルが指定されています (ole32.lib、advapi32.lib、user32.lib など、およびその他の非 MSVC 固有のものなど)。私の質問は.lib、静的リンクに使用されるファイルではないということですか? はいの場合、最終的な exe が約 500 KB しかないのはなぜですか? のいずれ.libもインポート ライブラリではありません。

    そうでない場合、linkデフォルトで静的または動的リンクを使用しますか? /MD指定された withclはここで効果がありますか?

4

1 に答える 1

3

元の C ランタイム ライブラリは、複数のモジュールから構築されたプログラムをサポートする必要があるとは想定されていませんでした。これには、およびのような暗黙的なグローバル状態を持つ関数errnoおよびのようなグローバル変数が含まれています。DLL を CRT の独自のコピーにリンクすることはできますが、DLL インターフェイスの設計方法に関してかなり厳しい要件が課せられます。CRT の状態に依存しないように十分に注意する必要がありますこれを間違えると、実行時の誤動作を診断することがほとんど不可能になります。stdoutstrtok()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 の依存関係が解決され、インポートされた関数は、プログラムの開始時にローダーによってバインドされます。

于 2014-06-17T10:54:59.243 に答える