リンカ ツール エラー LNK2001

更新 : 2007 年 11 月

エラー メッセージ

外部シンボル "symbol" は未解決です。

リンカは、コードが参照している関数、変数、ラベルなどをライブラリおよびオブジェクト ファイルから検索しましたが失敗しました。

このエラー メッセージに続いて、致命的なエラー LNK1120 が出力されます。

原因

  • マネージ ライブラリまたは Web サービス プロジェクトを Visual C++ 2003 からアップグレードすると、/Zl コンパイラ オプションが [コマンド ライン] プロパティ ページに追加されます。これによって LNK2001 が発生します。解決するには、/Zl を [コマンド ライン] プロパティ ページから削除します。詳細については、/Zl (既定のライブラリ名の省略) および「方法 : プロジェクト プロパティ ページを開く」を参照してください。または、msvcrt.lib および msvcmrt.lib をリンカの [Additional Dependencies] プロパティに追加します。

  • コードが、存在していないものを参照しています。シンボルのスペルが間違っていたり、大文字と小文字が誤っているなどの原因が考えられます。

  • コードが、正しくないものを要求しています。これは、ライブラリのバージョンを混在して使用している場合です。製品のあるバージョンと別のバージョンを同時に使用しています。

特定の原因

コーディングの問題

  • LNK2001 の診断テキストで、__check_commonlanguageruntime_version が未解決の外部シンボルであると報告された場合の解決方法については、「LNK2019」を参照してください。

  • メンバ テンプレートがクラスの外側で定義されています。Visual C++ では、メンバ テンプレートを囲まれたクラスの外で完全に定義する必要があるという制限があります。LNK2001 とメンバ テンプレートの詳細については、サポート技術情報の「PRB: LNK2001 on Template Member Functions (Q239436)」を参照してください。

  • コードとモジュール定義 (.def) ファイルとで大文字と小文字が異なっていると、LNK2001 エラーになります。たとえば、C++ ソース ファイルで変数名を var1 とし、.def ファイルで VAR1 を使用している場合です。

  • 関数のインライン展開を使用しているプロジェクトで、その関数をヘッダー ファイルではなく、.cpp ファイルで定義していると、LNK2001 エラーになることがあります。

  • C ++ プログラムから C 関数を呼び出すときに extern "C" を使用しないと、LNK2001 エラーになることがあります。extern "C" を使用することによって、コンパイラで C の名前付け規則が強制されます。コンパイラ オプション /Tp および /Tc を指定すると、ファイルの拡張子に関係なく、C++ または C のファイルとしてコンパイルされます。これらのオプションを指定することにより、関数名が予測したものと異なることがあります。

  • 外部リンケージのない関数またはデータを参照すると、LNK2001 エラーになることがあります。C++ では、インライン関数と const データには内部リンケージがあります。ただし、明示的に extern と指定された場合を除きます。

  • 関数本体または変数がないと、LNK2001 エラーになることがあります。関数のプロトタイプまたは extern 宣言だけでも、コンパイルはエラーなしで継続します。しかし関数コードや変数領域が解決されないため、リンカはアドレスの呼び出しや変数の参照を解決できません。

  • 関数宣言でのパラメータと一致していない関数を呼び出すと、LNK2001 エラーになることがあります。名前の装飾は、修飾された最終の関数名に関数のパラメータを取り込みます。

  • プロトタイプのインクルードを誤ると、コンパイラが存在しない関数本体を呼び出そうとして LNK2001 エラーになることがあります。関数 F をクラスおよびクラス以外の両方に実装している場合には、C++ のスコープ解決規則に注意してください。

  • C++ を使用するときにクラス定義に関数プロトタイプを含めると、クラスで使用する関数の実装のインクルードに失敗して LNK2001 エラーになることがあります。

  • 抽象基本クラスのコンストラクタまたはデストラクタから純粋仮想関数を呼び出すと、LNK2001 エラーになることがあります。純粋仮想関数には基本クラスの実装がありません。

  • 関数内部で宣言された変数 (ローカル変数) をその関数のスコープ外で使用すると、LNK2001 エラーになることがあります。

  • リリース バージョンの ATL プロジェクトをビルドするときに、CRT スタートアップ コードが必須になるように指定しています。これを修正するには、次のいずれかを行います。

    • CRT スタートアップ コードの組み込みを許可しているプリプロセッサ定義のリストから _ATL_MIN_CRT を削除します。詳細については、「[全般] プロパティ ページ (プロジェクト)」を参照してください。

    • 可能な場合は、CRT スタートアップ コードを必要とする CRT 関数の呼び出しを削除します。代わりに、Win32 で相当するものを使用します。たとえば、strcmp ではなく lstrcmp を使用します。CRT スタートアップ コードを必要とすることがわかっている関数は、一部の文字列関数および浮動小数点関数です。

コンパイルとリンクの問題

  • ライブラリ ファイル (.LIB) またはオブジェクト ファイル (.OBJ) への参照がプロジェクトにありません。詳細については、「リンカ入力としての .lib ファイル」を参照してください。

  • /NODEFAULTLIB または /Zl を使用する場合、必須コードを含むライブラリは、明示的にそれらを含めていない限り、プロジェクトにリンクされません (/clr または /clr:pure を指定してコンパイルする場合、.cctor への参照が表示されます。詳細については、「混在アセンブリの初期化」を参照してください)。

  • Unicode と MFC を使用するコードで wWinMainCRTStartup へのエントリ ポイントを作成していないときは、_WinMain@16 で未解決の外部エラーが発生します。/ENTRY オプションを使用してください。「Unicode プログラミングの要約」を参照してください。

    詳細については、MSDN ライブラリにある以下のサポート技術情報の文書を参照してください。MSDN ライブラリの [検索] タブをクリックし、トピック番号またはトピック タイトルをテキスト ボックスに貼り付けて、[検索開始] ボタンをクリックします。トピック番号を検索する場合は、[タイトルのみ検索] がオフになっていることを確認してください。

    • 「PRB: Error LNK2001: '_WinMain@16': Unresolved External Symbol (Q125750)」

    • 「PRB: Wrong Project Selection Causes LNK2001 on _WinMain@16 (Q131204)」

    • 「INFO: Unicode Support in the Microsoft Foundation Class Library (Q100639)」

    • 「PRB: Link Error LNK2001: Unresolved External Symbol _main (Q291952)」

  • /MT でコンパイルしたコードを LIBC.lib にリンクすると、_beginthread_beginthreadex_endthread、および _endthreadex で未解決の外部エラーになります。

  • マルチスレッド ライブラリ (MFC コードまたは /MT でコンパイルしたコード) を必要とするコードをリンクすると、_beginthread_beginthreadex_endthread、および _endthreadex で LNK2001 エラーが発生します。詳細については、以下のサポート技術情報の文書を参照してください。

    • 「PRB: Error Msg: LNK2001 on __beginthreadex and __endthreadex (Q126646)」

    • 「INFO: /Mx Compiler Options and the LIBC, LIBCMT, MSVCRT Libs (Q128641)」

    • 「PRB: MFC and CRT Must Match in debug/release and static/dynamic (Q166504)」

  • /MD を使用してコンパイルする場合、ランタイムの内容はすべて DLL に登録されているため、ソースで "func" を参照するとオブジェクトでは参照 "__imp__func" になります。スタティック ライブラリの LIBC.lib または LIBCMT.lib へのリンクを試みると、__imp__func で LNK2001 エラーが発生します。/MD を使わずに MSVCxx.lib へのリンクを試みる場合は、必ずしも LNK2001 エラーは発生しませんが、別の問題が発生することがあります。

  • アプリケーションをデバッグ バージョンでビルドするときにリリース モード ライブラリとリンクすると、LNK2001 エラーが発生します。同様に、/Mxd オプション (/MTd または /MDd) を使用したり _DEBUG を定義したりしてからリリース ライブラリとリンクする場合も、(他にも問題はありますが) 未解決の外部エラーが潜在的に発生します。リリース モードのビルドをデバッグ ライブラリとリンクしても同様の問題が発生します。

  • Microsoft ライブラリとコンパイラのバージョンを混在して使用すると、問題が発生することがあります。新バージョンのコンパイラに対応したライブラリには、以前のバージョンのライブラリにはない新しいシンボルが含まれているものもあります。検索パスのディレクトリの順序を変更するか、現在のバージョンを指すように変更する必要があります。

    検索順序は、[VC++ ディレクトリ] ダイアログ ボックス ([ツール] - [オプション] - [プロジェクト]) の [ディレクトリを表示するプロジェクト] の [ライブラリ ファイル] で変更できます。プロジェクトの [プロパティ ページ] ダイアログ ボックスの [リンカ] フォルダにも、古いパスが含まれている場合があります。

    この問題は、新しい SDK を以前と異なる場所にインストールし、検索順序が新しい場所を指すように更新されていない場合に発生することがあります。通常は、新しい SDK の include ディレクトリと lib ディレクトリへのパスを Visual C++ の既定の場所の前に挿入する必要があります。また、埋め込みパスを含むプロジェクトが、有効であっても古いパスを示し、このパスが別の場所にインストールされている新バージョンで追加された新機能には無効なパスである場合があります。

  • 現在では、コンパイラ販売元間またはコンパイラのバージョン間でさえも、C++ の名前付け規則が確立されていません。そのため、別のコンパイラでコンパイルされたオブジェクト ファイルをリンクすると、名前付け方式が異なるため LNK2001 エラーが発生します。

  • 異なるモジュールでインラインとインライン以外のコンパイラ オプションを混在させると LNK2001 が発生します。/Ob1 または /Ob2 によって関数のインライン展開を有効にして C++ ライブラリを作成した場合は、関数を記述する対応するヘッダー ファイルで inline キーワードを指定せずにインライン展開を無効にすると、このエラーが発生します。対策としては、他のファイルにインクルードするヘッダー ファイルに inline を使用してインライン関数を定義します。

  • #pragma inline_depth コンパイラ ディレクティブを使用する場合は、値 2 以上が設定されており/Ob1 または /Ob2 のコンパイラ オプションが使用されていることを確認します。

  • リソースだけの DLL を作成するときに LINK オプションの /NOENTRY を省略するとこのエラーが発生します。

  • /SUBSYSTEM または /ENTRY の設定が正しくないと、LNK2001 が発生することがあります。たとえば、文字ベースのアプリケーション (コンソール アプリケーション) を作成し、/SUBSYSTEM:WINDOWS を指定すると、WinMain の外部シンボルが解決されません。これらのオプションおよびエントリ ポイントの詳細については、リンカ オプション /SUBSYSTEM および /ENTRY に関するトピックを参照してください。

エクスポートの問題

  • 16 ビットから 32 ビットまたは 16 ビットから 64 ビットにアプリケーションを移植すると、LNK2001 が発生することがあります。現在のモジュール定義 (.def) ファイルの構文では、__cdecl、__stdcall、および __fastcall の各関数はアンダースコアを使用せずに (装飾形式で指定しないで) EXPORTS セクションにリストする必要があります。16 ビットの構文ではこれと異なり、アンダースコアを使用して (装飾形式で) 関数をリストする必要があります。詳細については、「モジュール定義 (.def) ファイル」の EXPORTS に関する説明を参照してください。

  • エクスポートが .def ファイルにリストされていても見つからない場合に、エラー LNK2001 が発生します。エクスポートが存在しない、スペルが間違っている、C++ の装飾名を使用している (.def ファイルでは C++ の装飾名を使用できません)、という原因が考えられます。

出力の解釈

シンボルが未解決な場合は、次のガイドラインに従って関数に関する情報を得ることができます。

x86 プラットフォームでは、C でコンパイルされる名前、または C++ での extern "C" の名前の呼び出し規約による装飾は、次のとおりです。

  • __cdecl
    関数名の先頭にアンダースコア (_) が付きます。

  • __stdcall
    関数名の先頭にアンダースコア (_) が付き、末尾にアット マーク (@) が付き、続いてスタックのパラメータのダブルワード境界整列のサイズが付きます。

  • __fastcall
    関数名の先頭と末尾にアット マーク (@) が付き、続いてスタックのパラメータのダブルワード境界整列のサイズが付きます。

undname.exe を使用すると、装飾名の装飾されていない形式を取得できます。

上に示したいくつかの原因の詳細については、「名前の装飾」を参照してください。