什么是未定义的引用/未解决的外部符号错误?什么是常见原因以及如何修复/预防它们?
按照2.2 的规定,编译 C++ 程序需要几个步骤:
翻译的语法规则之间的优先级由以下阶段指定[见脚注]。 如有必要,物理源文件字符以实现定义的方式映射到基本源字符集(为行尾指示符引入换行符)。[剪辑] 每个反斜杠字符 () 的实例后面紧跟一个换行符被删除,拼接物理源代码行以形成逻辑源代码行。[剪辑] 源文件被分解为预处理标记(2.5)和空白字符序列(包括注释)。[剪辑] 预处理指令被执行,宏调用被扩展,_Pragma 一元运算符表达式被执行。[剪辑] 字符文字或字符串文字中的每个源字符集成员,以及字符文字或非原始字符串文字中的每个转义序列和通用字符名称,都将转换为执行字符集的相应成员;[剪辑] 相邻的字符串文字标记被连接起来。 分隔标记的空白字符不再重要。每个预处理令牌都被转换为一个令牌。(2.7)。生成的标记在句法和语义上进行分析,并作为翻译单元进行翻译。[剪辑] 翻译后的翻译单元和实例化单元组合如下:[SNIP] 所有外部实体引用均已解析。链接库组件以满足对当前翻译中未定义的实体的外部引用。所有此类翻译器输出都被收集到程序映像中,该程序映像包含在其执行环境中执行所需的信息。(强调我的) [脚注]实现必须表现得好像这些单独的阶段发生一样,尽管在实践中不同的阶段可能被折叠在一起。
翻译的语法规则之间的优先级由以下阶段指定[见脚注]。
[脚注]实现必须表现得好像这些单独的阶段发生一样,尽管在实践中不同的阶段可能被折叠在一起。
指定的错误发生在编译的最后阶段,通常称为链接。这基本上意味着您将一堆实现文件编译成目标文件或库,现在您想让它们一起工作。
假设您a在a.cpp. 现在,b.cpp 声明该符号并使用它。在链接之前,它只是假设该符号是在某个地方定义的,但它并不关心在哪里。链接阶段负责找到符号并将其正确链接到b.cpp(嗯,实际上是到使用它的对象或库)。
a
a.cpp
b.cpp
如果您使用的是 Microsoft Visual Studio,您将看到项目生成.lib文件。其中包含导出符号表和导入符号表。导入的符号将根据您链接的库进行解析,并为使用它的库.lib(如果有)提供导出的符号。
.lib
其他编译器/平台也存在类似的机制。
常见的错误消息是Microsoft Visual Studio的error LNK2001,和GCC的symbolName。error LNK1120``error LNK2019``undefined reference to
error LNK2001
error LNK1120``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