什么是未定义的引用/未解析的外部符号错误以及如何修复它? [英] What is an undefined reference/unresolved external symbol error and how do I fix it?

查看:51
本文介绍了什么是未定义的引用/未解析的外部符号错误以及如何修复它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What are undefined reference/unresolved external symbol errors? What are common causes and how to fix/prevent them?

推荐答案

按照 2.2 (感谢 Keith Thompson 供参考):

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

The precedence among the syntax rules of translation is specified by the following phases [see footnote].

  1. 物理源文件字符以实现定义的方式映射到基本源字符集(为行尾指示符引入换行符)如果必要的.[SNIP]
  2. 每个反斜杠字符 () 后面紧跟一个换行符的实例都被删除,将物理源行拼接为形成逻辑源代码行.[SNIP]
  3. 源文件被分解为预处理标记 (2.5) 和空白字符序列(包括注释).[SNIP]
  4. 执行预处理指令,扩展宏调用,并执行 _Pragma 一元运算符表达式.[SNIP]
  5. 字符文字或字符串文字中的每个源字符集成员,以及每个转义序列和通用字符名称在字符文字或非原始字符串文字中,转换为执行字符集的对应成员;[SNIP]
  6. 连接相邻的字符串文字标记.
  7. 分隔标记的空白字符不再重要.每个预处理令牌都被转换为一个令牌.(2.7).这结果标记在句法和语义上进行分析和翻译为翻译单元.[SNIP]
  8. 翻译的翻译单元和实例化单元的组合如下:[SNIP]
  9. 解析所有外部实体引用.链接库组件以满足对未定义的实体的外部引用当前翻译.所有这些翻译输出都被收集到一个包含执行所需信息的程序映像执行环境.(强调我的)
  1. Physical source file characters are mapped, in an implementation-defined manner, to the basic source character set (introducing new-line characters for end-of-line indicators) if necessary. [SNIP]
  2. Each instance of a backslash character () immediately followed by a new-line character is deleted, splicing physical source lines to form logical source lines. [SNIP]
  3. The source file is decomposed into preprocessing tokens (2.5) and sequences of white-space characters (including comments). [SNIP]
  4. Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. [SNIP]
  5. Each source character set member in a character literal or a string literal, as well as each escape sequence and universal-character-name in a character literal or a non-raw string literal, is converted to the corresponding member of the execution character set; [SNIP]
  6. Adjacent string literal tokens are concatenated.
  7. White-space characters separating tokens are no longer significant. Each preprocessing token is converted into a token. (2.7). The resulting tokens are syntactically and semantically analyzed and translated as a translation unit. [SNIP]
  8. Translated translation units and instantiation units are combined as follows: [SNIP]
  9. All external entity references are resolved. Library components are linked to satisfy external references to entities not defined in the current translation. All such translator output is collected into a program image which contains information needed for execution in its execution environment. (emphasis mine)

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

[footnote] Implementations must behave as if these separate phases occur, although in practice different phases might be folded together.

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

The specified errors occur during this last stage of compilation, most commonly referred to as linking. It basically means that you compiled a bunch of implementation files into object files or libraries and now you want to get them to work together.

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

Say you defined symbol a in a.cpp. Now, b.cpp declared that symbol and used it. Before linking, it simply assumes that that symbol was defined somewhere, but it doesn't yet care where. The linking phase is responsible for finding the symbol and correctly linking it to b.cpp (well, actually to the object or library that uses it).

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

If you're using Microsoft Visual Studio, you'll see that projects generate .lib files. These contain a table of exported symbols, and a table of imported symbols. The imported symbols are resolved against the libraries you link against, and the exported symbols are provided for the libraries that use that .lib (if any).

其他编译器/平台也有类似的机制.

Similar mechanisms exist for other compilers/ platforms.

常见的错误消息有 error LNK2001error LNK1120error LNK2019(用于 Microsoft Visual Studio)>未定义引用 symbolName for GCC.

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 会产生以下错误:

will generate the following errors with 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>...	est2.exe : fatal error LNK1120: 4 unresolved externals

常见原因包括:

  • Failure to link against appropriate libraries/object files or compile implementation files
  • Declared and undefined variable or function.
  • Common issues with class-type members
  • Template implementations not visible.
  • Symbols were defined in a C program and used in C++ code.
  • Incorrectly importing/exporting methods/classes across modules/dll. (MSVS specific)
  • Circular library dependency
  • undefined reference to `WinMain@16'
  • Interdependent library order
  • Multiple source files of the same name
  • Mistyping or not including the .lib extension when using the #pragma (Microsoft Visual Studio)
  • Problems with template friends
  • Inconsistent UNICODE definitions
  • Missing "extern" in const variable declarations/definitions (C++ only)

这篇关于什么是未定义的引用/未解析的外部符号错误以及如何修复它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆