未定義の参照/未解決の外部シンボル エラーとは何ですか? 一般的な原因は何ですか? また、これらのエラーを修正および防止するにはどうすればよいですか?
ベストアンサー1
次のようなコードがあるとします。
// a.cpp
int get() { return 0; }
// b.cpp
int get(); // usually, one doesn't write this directly, but gets these
// declarations from included header files
int x = get();
をコンパイルするときb.cpp
、コンパイラは単にシンボルがどこかでget()
定義されていると想定しますが、どこで定義されているかはまだ考慮しません。リンク フェーズでは、シンボルを見つけて、およびから生成されたオブジェクト ファイルを正しくリンクする役割を担います。a.cpp
b.cpp
a.cpp
を定義しなかった場合get
、「未定義の参照」または「未解決の外部シンボル」というリンカー エラーが発生します。
C++ 標準の文言
C++プログラムのコンパイルは、以下のいくつかのフェーズで行われます。[語彙フェーズ]最後の部分が関連しています:
9.すべての外部エンティティ参照が解決されます。ライブラリ コンポーネントは、現在の翻訳で定義されていないエンティティへの外部参照を満たすようにリンクされます。このようなトランスレータ出力はすべて、実行環境での実行に必要な情報を含むプログラム イメージに収集されます。
見るキース・トンプソンの回答これらのフェーズの概要については、こちらをご覧ください。
指定されたエラーは、コンパイルのこの最終段階、一般的にはリンクと呼ばれる段階で発生します。基本的には、一連のソース ファイルをオブジェクト ファイルまたはライブラリにコンパイルし、それらを連携させる必要があることを意味します。
実際のリンカーエラー
Microsoft Visual Studio を使用している場合は、プロジェクトによってファイルが生成されることがわかります.lib
。これらには、エクスポートされたシンボルのテーブルとインポートされたシンボルのテーブルが含まれます。インポートされたシンボルは、リンク先のライブラリに対して解決され、エクスポートされたシンボルは、それを使用するライブラリ.lib
(存在する場合) に提供されます。
他のコンパイラ/プラットフォームにも同様のメカニズムが存在します。
一般的なエラー メッセージはerror LNK2001
、Microsoft Visual Studioの場合はerror LNK1120
、、GCCの場合はsymbolNameです。error LNK2019
undefined reference to
コード:
struct X
{
virtual void foo();
};
struct Y : X
{
void foo() {}
};
struct A
{
virtual ~A() = 0;
};
struct B: A
{
virtual ~B(){}
};
extern int x;
void foo();
int main()
{
x = 0;
foo();
Y y;
B b;
}
GCCでは次のエラーが発生します。
/home/AbiSfw/ccvvuHoX.o: In function `main':
prog.cpp:(.text+0x10): undefined reference to `x'
prog.cpp:(.text+0x19): undefined reference to `foo()'
prog.cpp:(.text+0x2d): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o: In function `B::~B()':
prog.cpp:(.text._ZN1BD1Ev[B::~B()]+0xb): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o: In function `B::~B()':
prog.cpp:(.text._ZN1BD0Ev[B::~B()]+0x12): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1Y[typeinfo for Y]+0x8): undefined reference to `typeinfo for X'
/home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1B[typeinfo for B]+0x8): undefined reference to `typeinfo for A'
collect2: ld returned 1 exit status
Microsoft Visual Studioでも同様のエラーが発生します:
1>test2.obj : error LNK2001: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ)
1>test2.obj : error LNK2001: unresolved external symbol "int x" (?x@@3HA)
1>test2.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall A::~A(void)" (??1A@@UAE@XZ)
1>test2.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall X::foo(void)" (?foo@X@@UAEXXZ)
1>...\test2.exe : fatal error LNK1120: 4 unresolved externals
一般的な原因
- 適切なライブラリ/オブジェクトファイルへのリンクまたは実装ファイルのコンパイルの失敗
- 宣言されたが未定義の変数または関数。
- クラス型メンバーの一般的な問題
- テンプレートの実装は表示されません。
- シンボルは C プログラムで定義され、C++ コードで使用されました。
- モジュール/DLL 間でメソッド/クラスを誤ってインポート/エクスポートします。(MSVS 固有)
- 循環ライブラリ依存関係
- `WinMain@16' への未定義の参照
- 相互依存ライブラリ順序
- 同じ名前の複数のソースファイル
#pragma
(Microsoft Visual Studio)を使用する際に .lib 拡張子を誤って入力したり、含めなかったりする- テンプレート友達の問題
- 一貫性のない
UNICODE
定義 - const 変数の宣言/定義に「extern」がありません (C++ のみ)
- Visual Studio Code が複数ファイル プロジェクト用に構成されていません
- Mac OS X では dylib をビルドするときにエラーが発生しますが、他の Unix 系システムでは .so は問題ありません。
- リンケージは、それを参照するオブジェクトファイルよりも先にライブラリを消費します。
- リンケージには、異なる C++ コンパイラから生成された C++ オブジェクト ファイルと C++ ライブラリが含まれています。