什么是未定义的引用/未解决的外部符号错误,我该如何解决?

新手上路,请多包涵

什么是未定义的引用/未解决的外部符号错误?什么是常见原因以及如何修复/预防它们?

原文由 Luchian Grigore 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

按照 2.2 的规定,编译 C++ 程序需要几个步骤 (参考 Keith Thompson)

翻译的语法规则之间的优先级由以下阶段指定 [见脚注]

  1. 如有必要,物理源文件字符以实现定义的方式映射到基本源字符集(为行尾指示符引入换行符)。 [剪辑]
  2. 每个反斜杠字符 (\) 的实例后面紧跟一个换行符被删除,拼接物理源代码行以形成逻辑源代码行。 [剪辑]
  3. 源文件被分解为预处理标记(2.5)和空白字符序列(包括注释)。 [剪辑]
  4. 执行预处理指令,扩展宏调用,并执行 _Pragma 一元运算符表达式。 [剪辑]
  5. 字符文字或字符串文字中的每个源字符集成员,以及字符文字或非原始字符串文字中的每个转义序列和通用字符名称,都将转换为执行字符集的相应成员; [剪辑]
  6. 相邻的字符串文字标记被连接起来。
  7. 分隔标记的空白字符不再重要。每个预处理令牌都被转换为一个令牌。 (2.7)。生成的标记在句法和语义上进行分析,并作为翻译单元进行翻译。 [剪辑]
  8. 翻译后的翻译单元和实例化单元组合如下: [SNIP]
  9. 所有外部实体引用均已解析。链接库组件以满足对当前翻译中未定义的实体的外部引用。所有此类翻译器输出都被收集到程序映像中,该程序映像包含在其执行环境中执行所需的信息。 (强调我的)

[脚注] 实现必须表现得好像这些单独的阶段发生了一样,尽管在实践中不同的阶段可能被折叠在一起。

指定的错误发生在编译的最后阶段,通常称为链接。这基本上意味着您将一堆实现文件编译成目标文件或库,现在您想让它们一起工作。

假设您在 --- 中定义了符号 a a.cpp 。现在, b.cpp 声明 了该符号并使用了它。在链接之前,它只是假设该符号是在 某个地方 定义的,但它并不关心在哪里。链接阶段负责找到符号并将其正确链接到 b.cpp (实际上是使用它的对象或库)。

如果您使用的是 Microsoft Visual Studio,您会看到项目生成 .lib 文件。其中包含导出符号表和导入符号表。导入的符号将根据您链接的库进行解析,并为使用 .lib (如果有)的库提供导出的符号。

其他编译器/平台也存在类似的机制。

Common error messages are error LNK2001 , error LNK1120 , error LNK2019 for Microsoft Visual Studio and undefined reference to symbolName for 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

常见原因包括:

原文由 Luchian Grigore 发布,翻译遵循 CC BY-SA 4.0 许可协议

将 Visual Studio Code 与 Code Runner 扩展和多个 .c 或 .cpp 文件一起使用

随附的 Code Runner 仅适用于具有单个源文件的已编译程序。它不是为与多个源文件一起使用而设计的。您应该使用不同的扩展名,例如 C/C++ Makefile Project 扩展名或 CMake Tools 扩展名,或者 修复 Code Runner 扩展名以处理多个文件,或者只是手动编辑您的 .json 配置文件。

原文由 n. 1.8e9-where’s-my-share m. 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题