リンカ ツール エラー LNK2005

symbol は既にオブジェクトで定義されています

シンボル シンボル が複数回定義されました。

このエラーの後に、致命的なエラー LNK1169 が発生します。

考えられる原因と解決策

一般に、このエラーは 1 つの定義ルール に違反したことを意味します。このルールでは、任意のオブジェクト ファイル内で使用されるテンプレート、関数、型、またはオブジェクトに対して 1 つの定義のみ、また外部から見えるオブジェクトまたは関数に対しては実行ファイル全体で 1 つの定義のみ許可します。

このエラーの一般的な原因をいくつか次に示します。

  • このエラーは、ヘッダーファイルで変数が定義されている場合に発生する可能性があります。 たとえば、プロジェクト内の複数のソース ファイルにこのヘッダー ファイルを含めると、次のようなエラーが発生します。

    // LNK2005_global.h
    int global_int;  // LNK2005
    

    考えられる解決策:

    • ヘッダー ファイル extern int global_int; で変数 extern を宣言します。次に、それを定義し、必要に応じて1つのソース ファイル int global_int = 17; で初期化します。 これで、この変数は、ヘッダー ファイルをインクルードするなどして extern 宣言することで、どのソース ファイルでも使えるグローバルになりました。 グローバルにしなければならない変数に対しては、このソリューションを推奨しますが、優れたソフトウェア エンジニアリングによってもグローバル変数が最小限に抑えられます。

    • 変数を static で宣言します: static int static_int = 17;。 これにより、定義のスコープが現在のオブジェクトファイルに限定され、複数のオブジェクト ファイルで変数の独自のコピーを持つことができます。 グローバル変数と混同する可能性があるため、ヘッダー ファイルに静的変数を定義することは推奨しません。 静的変数の定義は、それらを使用するソース ファイルに移動することを推奨します。

    • 変数を selectany で宣言します: __declspec(selectany) int global_int = 17;。 これでリンカーに、すべての外部参照で使用する 1 つの定義を選択し、残りを破棄するように指示します。 このソリューションは、インポート ライブラリを組み合わせるときに便利な場合があります。 それ以外の場合は、リンカー エラーを回避する方法として推奨されません。

  • このエラーは、ヘッダー ファイルが inline でない関数を定義している場合に発生する可能性があります。 複数のソース ファイルにこのヘッダー ファイルを含めると、実行可能ファイルで関数の複数の定義が取得されます。

    // LNK2005_func.h
    int sample_function(int k) { return 42 * (k % 167); }  // LNK2005
    

    考えられる解決策:

    • inline キーワードを関数に追加します:

      // LNK2005_func_inline.h
      inline int sample_function(int k) { return 42 * (k % 167); }
      
    • ヘッダー ファイルから関数本体を削除し、宣言だけを残して、関数を 1 つのソース ファイルにのみ実装します。

      // LNK2005_func_decl.h
      int sample_function(int);
      
      // LNK2005_func_impl.cpp
      int sample_function(int k) { return 42 * (k % 167); }
      
  • このエラーは、ヘッダー ファイル内のクラス宣言の外部でメンバー関数を定義した場合にも発生する可能性があります。

    // LNK2005_member_outside.h
    class Sample {
    public:
        int sample_function(int);
    };
    int Sample::sample_function(int k) { return 42 * (k % 167); }  // LNK2005
    

    この問題を解決するには、メンバー関数の定義をクラス内で移動します。 クラス宣言内で定義されているメンバー関数は、暗黙的にインライン化されます。

    // LNK2005_member_inline.h
    class Sample {
    public:
        int sample_function(int k) { return 42 * (k % 167); }
    };
    
  • このエラーは、標準ライブラリまたは CRT の複数のバージョンをリンクした場合に発生する可能性があります。 たとえば、製品とデバッグ両方の CRT ライブラリ、またはライブラリの静的バージョンと動的バージョンの両方、または 2 つの異なるバージョンの標準ライブラリを実行可能ファイルにリンクしようとすると、このエラーが何回も報告されることがあります。 この問題を解決するには、リンク コマンドから各ライブラリのコピーを 1 つ以外すべて削除してください。 製品版とデバッグ用のライブラリ、または異なるバージョンのライブラリを同じ実行可能ファイルに混在させることは推奨しません。

    既定以外のライブラリを使用するようリンカーに指示するには、コマンドラインで、使用するライブラリを指定し、/NODEFAULTLIB オプションを使用して既定のライブラリを無効にします。 IDE でプロジェクトに参照を追加して使用するライブラリを指定し、プロジェクトの [Property Pages (プロパティ ページ)] ダイアログを開き、[リンカー][入力] のプロパティ ページで、[Ignore All Default Libraries (すべての既定のライブラリを無視する)][Ignore Specific Default Libraries (特定の既定ライブラリを無視する)] のいずれかのプロパティを設定して既定のライブラリを無効化できます。

  • このエラーは、/clr オプションを使用する際、静的ライブラリと動的ライブラリを組み合わせて使用した場合に発生する可能性があります。 たとえば、静的 CRT 内のリンクを実行可能ファイルで使用するために DLL をビルドすると、このエラーが発生する可能性があります。 この問題を解決するには、実行可能ファイルで使用するためにビルドするすべてのライブラリに対して、静的ライブラリのみを使用するか、動的ライブラリを使用します。

  • このエラーは、シンボルがパッケージ化された関数 (/Gy でコンパイルして作成) で、それが複数のファイルに含まれていたが、コンパイル間で変更された場合に発生する可能性があります。 この問題を解決するには、パッケージ化された関数を含むすべてのファイルを再コンパイルします。

  • このエラーは、シンボルが異なるライブラリの 2 つのメンバー オブジェクトで異なって定義されており、両方のメンバー オブジェクトが使用されている場合に発生する可能性があります。 ライブラリが静的にリンクされているときにこの問題を解決する方法の 1 つは、1 つのライブラリのメンバー オブジェクトを使用し、そのライブラリを最初にリンカー コマンドラインに含めることです。 両方のシンボルを使用するには、それらを区別する方法を作成する必要があります。 たとえば、ソースからライブラリをビルドできる場合は、各ライブラリを一意の名前空間にラップできます。 または、一意の名前を使用して元のライブラリへの参照をラップする新しいラッパー ライブラリを作成し、新しいライブラリを元のライブラリにリンクしてから、実行可能ファイルを元のライブラリではなく新しいライブラリにリンクすることもできます。

  • このエラーは、extern const 変数が 2 回定義されており、それぞれの定義に異なる値がある場合に発生する可能性があります。 この問題を解決するには、定数を1回だけ定義するか、名前空間または enum class 定義を使用して定数を区別します。

  • uuid.lib を GUID を定義する他の .lib ファイル (例えば oledb.lib や adsiid.lib) と組み合わせて使用すると、このエラーが発生する可能性があります。 次に例を示します。

    oledb.lib(oledb_i.obj) : error LNK2005: _IID_ITransactionObject
    already defined in uuid.lib(go7.obj)
    

    修正するには、リンカーのコマンド ライン オプションに /FORCE:MULTIPLE を追加し、uuid.lib が最初に参照されるライブラリであることを確認します。