假设你有以下代码:
// 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
,您将收到一个链接器错误,提示“未定义的引用”或“未解析的外部符号”。
中指定的几个阶段进行 [lex.phases] ,其中最后一个阶段是相关的:
9. 解析所有外部实体引用。链接库组件以满足对当前翻译中未定义的实体的外部引用。所有此类翻译器输出都被收集到程序映像中,该程序映像包含在其执行环境中执行所需的信息。
请参阅 Keith Thompson 的回答 以了解这些阶段的摘要。
指定的错误发生在编译的最后阶段,通常称为链接。这基本上意味着您将一堆源文件编译成目标文件或库,现在您想让它们一起工作。
如果您使用的是 Microsoft Visual Studio,则会看到项目生成 .lib
文件。这些文件包含一个导出符号表和一个导入符号表。导入的符号会根据您链接的库进行解析,导出的符号会提供给使用该符号的库 .lib
(如果有)。
其他编译器/平台也存在类似的机制。
常见错误消息 error LNK2001
, error LNK1120
, error LNK2019
针对 Microsoft Visual Studio ,而 undefined reference to
symbolName 针对 GCC .
代码:
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