次の方法で共有


リンカー ツール エラー LNK2019

関数 'function' で参照されている未解決の外部シンボル 'symbol'

function のコンパイルされたコードは symbol への参照または呼び出しを行いますが、リンカーはライブラリまたはオブジェクト ファイル内のいずれにもそのシンボル定義を見つけることができません。

このエラー メッセージの後に、致命的なエラー LNK1120 が発生します。 エラー LNK1120 を修正するには、最初に LNK2001 エラーと LNK2019 エラーを修正する必要があります。

考えられる原因

このエラーを受け取る方法は多数あります。 これらはすべて、リンカーが解決できなかった、または定義を見つけられなかった関数や変数への参照を含んでいます。 コンパイラは、シンボルが宣言済でない場合は識別できますが、シンボルが定義済でない場合は識別できません。 これは、その定義が別のソース ファイルまたはライブラリ内にある可能性があるためです。 シンボルが参照されているが定義されていない場合、リンカーは未解決の外部シンボル エラーを生成します。

LNK2019 エラーが発生する一般的な問題には次のものがあります。

シンボルの定義を含むソース ファイルがコンパイルされていません

Visual Studio では、シンボルを定義したソース ファイルがプロジェクトの一部としてコンパイルされていることを確認してください。 中間ビルド出力ディレクトリで、一致する .obj ファイルを確認します。 ソース ファイルがコンパイルされていない場合は、ソリューション エクスプローラー内のファイルを右クリックしてから、[プロパティ] を選択して、そのファイルのプロパティを確認します。 [構成プロパティ] > [General (一般)] ページにアイテムの種類として C/C++ コンパイラが表示されるはずです。 コマンド ラインで、定義を含むソース ファイルがコンパイル済みである必要があります。

シンボルの定義を含むオブジェクト ファイルまたはライブラリがリンクされていない

Visual Studio では、シンボル定義を含むオブジェクトファイルまたはライブラリが、プロジェクトの一部としてリンクされていることを確認してください。 コマンド ラインで、リンクするファイルの一覧にオブジェクト ファイルまたはライブラリがインクルードされることを確認してください。

シンボルの宣言とシンボルの定義でスペルが異なる

宣言と定義の両方、シンボルが使用または呼び出される場所で、正しいスペルと大文字化を使用していることを確認します。

関数が使用されているが、パラメーターの型または数が関数の定義と一致していない

関数の宣言は、定義と一致している必要があります。 関数の呼び出しが宣言と一致することと、宣言が定義と一致することを確認します。 関数テンプレートを呼び出すコードには、その定義と同じテンプレート パラメーターを含む、一致する関数テンプレート宣言も必要です。 テンプレート宣言の不一致の例については、例セクションのサンプル LNK2019e.cpp を参照してください。

宣言されている関数または変数が定義されていない

LNK2019 は、ヘッダー ファイルに宣言が存在するが、一致する定義が実装されていない場合に発生する可能性があります。 メンバー関数または static データ メンバーの場合、実装にはクラス スコープ セレクターを含める必要があります。 例については、「 Missing Function Body or Variable」を参照してください。

呼び出し規則が関数宣言と関数定義で異なる

一部の呼び出し規則 (__cdecl__stdcall__fastcall__vectorcall) は、装飾名の一部としてエンコードされます。 呼び出し規則が同じであることを確認します。

シンボルは C ファイル内で定義されているが、C++ ファイル内で extern "C" を使用せずに宣言されている

C としてコンパイルされたファイルは、extern "C"修飾子を使用しない限り、C++ ファイルで宣言された同じsymbolsの修飾名とは異なるsymbolsの修飾名を作成します。 シンボルごとに宣言がコンパイル リンケージと一致することを確認してください。 同様に、C++ ファイルで定義されているシンボルを C プログラムで使用する場合にも、定義の中で extern "C" を使用します。

static として定義されているシンボルが、後でファイルの外側から参照されている

C++ では、C とは異なり、 グローバル定数static リンケージを持ちます。 この制限を回避するには、 const 初期化をヘッダー ファイルに組み込み、そのヘッダーを .cpp ファイルにインクルードします。あるいは、変数を非定数にし、定数参照を使用してそれにアクセスすることもできます。

クラスの static メンバーが定義されていません

static クラス メンバーは一意に定義する必要があります。そうしないと、単一定義規則に違反します。 インラインで定義できない static クラス メンバーは、完全修飾名を使用して 1 つのソース ファイル内で定義する必要があります。 それがまったく定義されていない場合、リンカーは LNK2019 を生成します。

ビルドの依存関係がソリューション内でのプロジェクトの依存関係としてのみ定義されている

前のバージョンの Visual Studio では、このレベルの依存関係で十分でした。 しかし、Visual Studio 2010 以降、Visual Studio ではプロジェクト間参照が必要になりました。 プロジェクトにプロジェクト間の参照がない場合は、このリンカー エラーが発生することがあります。 この問題を修正するには、プロジェクト間参照を追加します。

エントリ ポイントが定義されていない

アプリケーション コードでは、コンソールアプリケーションの場合は適切なエントリ ポイント main または wmain、Windows アプリケーションの場合は WinMain または wWinMain を定義する必要があります。 詳細については、「main 関数とコマンド ライン引数」または WinMain 関数に関するページを参照してください。 カスタム エントリ ポイントを使用するには、/ENTRY (エントリ ポイント シンボル) リンカー オプションを指定します。

Windows アプリケーション用の設定を使用してコンソール アプリケーションをビルドしている

エラー メッセージが関数で参照WinMain未解決の外部シンボルに似ている場合は function_name/SUBSYSTEM:WINDOWSの代わりに/SUBSYSTEM:CONSOLEを使用してリンクします。 この設定の詳細と、Visual Studio 内でこのプロパティを設定する方法の手順については、「/SUBSYSTEM (サブシステムの指定)」を参照してください。

コードにリンクされているライブラリとオブジェクト ファイルは、コードと同じアーキテクチャ用にコンパイルする必要があります。 プロジェクトが参照するライブラリが、プロジェクトと同じアーキテクチャ用にコンパイルされている必要があります。 /LIBPATH または追加のライブラリ ディレクトリのプロパティが、正しいアーキテクチャ用にビルドされたライブラリを指していることを確認します。

異なるソース ファイル内でインライン展開されている関数に対して異なるコンパイラ オプションを使用しています

.cpp ファイルで定義されている関数のインライン展開を使用している場合に、異なるソース ファイルで関数のインライン展開のコンパイラ オプションが混在していると、LNK2019 が発生することがあります。 詳細については、「 Function Inlining Problems」を参照してください。

自動変数をそのスコープ外で使用している

自動変数 (関数スコープ) は、その関数のスコープ内でのみ使用できます。 これらの変数を extern として宣言して他のソース ファイルで使用することはできません。 例については、「 Automatic (Function Scope) Variables」を参照してください。

ターゲット アーキテクチャでサポートされていない組み込み関数を呼び出しているか、そのような組み込み関数に引数の型を渡している

たとえば、 AVX2 組み込みを使用するが、 /ARCH:AVX2 コンパイラ オプションを指定しない場合、コンパイラは組み込みが外部関数であると見なします。 コンパイラは、インライン命令を生成するのではなく、組み込みと同じ名前で外部シンボルへの呼び出しを生成します。 リンカーは、欠落しているこの関数の定義を検索しようとして、LNK2019 を生成します。 ターゲット アーキテクチャでサポートされている組み込み関数と型のみを使用していることを確認してください。

ネイティブの wchar_t を使用するコードとそれを使用しないコードが混在している

Visual Studio 2005 で行われた C++ 言語への準拠作業により、wchar_t は既定でネイティブ型になりました。 すべてのファイルで同じ /Zc:wchar_t 設定を使用してコンパイルされていない場合は、型参照が互換性のある型に解決されないことがあります。 すべてのライブラリ ファイルとオブジェクト ファイルの wchar_t 型に互換性があることを確認してください。 wchar_t の型定義から更新するか、コンパイル時に一貫した /Zc:wchar_t の設定を使用します。

Visual Studio 2015 より前のバージョンの Visual Studio を使用してビルドされた static ライブラリでは、UCRT にリンクすると LNK2019 エラーが発生することがあります。 UCRT ヘッダー ファイル <stdio.h><conio.h><wchar.h> では、多くの *printf**scanf* のバリエーションが inline 関数として定義されるようになりました。 インライン関数は、より小さな一連の共通関数によって実装されます。 インライン関数の個々の exports は、一般的な関数のみをエクスポートする標準 UCRT ライブラリでは使用できません。 この問題を解決するには、いくつかの方法があります。 推奨される方法は、現在のバージョンの Visual Studio を使用してレガシ ライブラリをリビルドすることです。 エラーの原因となった *printf* および *scanf* 関数の定義で、ライブラリ コードに標準ヘッダーを必ず使用してください。 リビルドできないレガシ ライブラリに対するもう 1 つのオプションは、リンクするライブラリのリストに legacy_stdio_definitions.lib を追加することです。 このライブラリ ファイルは、UCRT ヘッダーにインライン化された*printf*および*scanf*関数のsymbolsを提供します。 詳細については、「アップグレード時の潜在的な問題の概要」の中の「ライブラリ」セクションを参照してください。

サードパーティ ライブラリの問題と vcpkg

ビルドの一部としてサード パーティ製ライブラリを構成しようとした際にこのエラーが表示される場合は、vcpkg の使用を検討してください。 vcpkg は、既存の Visual Studio ツールを使用してライブラリをインストールおよびビルドする C++ パッケージ マネージャーです。 vcpkg は大規模なサードパーティ製ライブラリのリストをサポートしており、その数は増えています。 プロジェクトの一部として、ビルドの成功に必要なすべての構成プロパティと依存関係が設定されます。

診断ツール

リンカーが特定のシンボル定義を見つけられない理由を説明するのが難しい場合があります。 多くの場合、その定義を含むコードをビルドに含めていないことが問題となります。 または、ビルド オプションによって、外部 symbolsに対して異なる装飾名が作成されています。 LNK2019 エラーを診断するために役立ついくつかのツールとオプションを紹介します。

  • /VERBOSE リンカー オプションを使用すると、リンカーがどのファイルを参照しているかを確認できます。 このオプションは、シンボルの定義の入ったファイルがビルドに含まれているかどうかを確認するために役立ちます。

  • DUMPBIN ユーティリティの/EXPORTSオプションと/SYMBOLSオプションは、.dllおよびオブジェクトまたはライブラリ ファイルで定義されているsymbolsを検出するのに役立ちます。 エクスポートされた装飾名が、リンカーで検索する装飾名と一致することを確認してください。

  • UNDNAME ユーティリティでは、修飾された名前に対して同等の非装飾外部シンボルを表示できます。

ここでは、LNK2019 エラーが発生するコード例のいくつかを、そのエラーを修正する方法に関する情報と一緒に紹介します。

シンボルが宣言されているが、定義されていない

この例では、外部変数は宣言されていますが、定義されていません。

// LNK2019.cpp
// Compile by using: cl /EHsc /W4 LNK2019.cpp
// LNK2019 expected
extern char B[100];   // B isn't available to the linker
int main() {
   B[0] = ' ';   // LNK2019
}

変数と関数が extern として宣言されているものの、定義がされていない別の例を次に示します。

// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
   i++;
   g();
}
int main() {}

ig がビルドに含まれるいずれかのファイルで定義されていなければ、リンカーは LNK2019 を生成します。 このエラーを修正するには、定義を含むソース コード ファイルをコンパイルの一部に組み込みます。 または、その定義を含んだ .obj ファイルまたは .lib ファイルをリンカーに渡すことができます。

static データ メンバーが宣言されているが、定義されていない

LNK2019 は、static データ メンバーが宣言されているものの定義がなされていない場合に発生することもあります。 次の例は LNK2019 を生成します。その修正方法も示しています。

// LNK2019b.cpp
// Compile by using: cl /EHsc LNK2019b.cpp
// LNK2019 expected
struct C {
   static int s;
};

// Uncomment the following line to fix the error.
// int C::s;

int main() {
   C c;
   C::s = 1;
}

宣言パラメーターが定義と一致しません

関数テンプレートを呼び出すコードには、一致する関数テンプレート宣言が必要です。 宣言には、定義と同じテンプレート パラメーターを含める必要があります。 次の例では、ユーザー定義の演算子で LNK2019 が発生します。その修正方法も示しています。

// LNK2019e.cpp
// compile by using: cl /EHsc LNK2019e.cpp
// LNK2019 expected
#include <iostream>
using namespace std;

template<class T> class
Test {
   // The operator<< declaration doesn't match the definition below:
   friend ostream& operator<<(ostream&, Test&);
   // To fix, replace the line above with the following:
   // template<typename T> friend ostream& operator<<(ostream&, Test<T>&);
};

template<typename T>
ostream& operator<<(ostream& os, Test<T>& tt) {
   return os;
}

int main() {
   Test<int> t;
   cout << "Test: " << t << endl;   // LNK2019 unresolved external
}

一貫性のない wchar_t 型の定義

このサンプルでは、WCHAR を使用する export を持つ DLL を作成し、wchar_t に解決しています。

// LNK2019g.cpp
// compile with: cl /EHsc /LD LNK2019g.cpp
#include "windows.h"
// WCHAR resolves to wchar_t
__declspec(dllexport) void func(WCHAR*) {}

次のサンプルでは、前のサンプルの DLL を使用し、unsigned short*WCHAR* の型が同じではないため、LNK2019 が生成されます。

// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);

int main() {
   func(0);
}

このエラーを修正するには、unsigned shortwchar_t または WCHAR に変更するか、/Zc:wchar_t- を使用して LNK2019g.cpp をコンパイルしてください。

関連項目

LNK2019、LNK2001、LNK1120 エラーの考えられる原因とソリューションの詳細については、Stack Overflow の質問「What is an undefined reference/unresolved external symbol error and how do I fix it?」を参照してください。