什么是未定义的参考/未解决的外部符号错误?常见原因是什么?如何解决/预防它们?

随意编辑/添加自己的。

最佳答案

如2.2 (credits to Keith Thompson for the reference)所指定,编译C ++程序分几步进行:


  翻译的语法规则中的优先级由以下阶段指定[请参见脚注]。
  
  
  物理源文件字符以实现定义的方式映射到基本源字符集
  (为行尾指示器引入换行符),如果
  必要。 [SNIP]
  立即删除一个反斜杠字符(\)并紧跟换行符的每个实例,将物理源代码行拼接到
  形成逻辑源代码行。 [SNIP]
  源文件被分解为预处理令牌(2.5)和空白字符序列(包括注释)。 [SNIP]
  执行预处理指令,扩展宏调用,并执行_Pragma一元运算符表达式。 [SNIP]
  字符文字或字符串文字中的每个源字符集成员,以及每个转义序列和通用字符名称
  在字符文字或非原始字符串文字中,将转换为
  执行字符集的相应成员; [SNIP]
  相邻的字符串文字标记是串联在一起的。
  分隔标记的空格字符不再重要。每个预处理令牌都将转换为令牌。 (2.7)。的
  由此产生的令牌在语法和语义上进行了分析,
  作为翻译单位进行翻译。 [SNIP]
  翻译的翻译单元和实例化单元的组合如下:[SNIP]
  所有外部实体引用均已解决。库组件被链接起来,以满足外部引用中未定义的实体
  当前的翻译。所有这样的翻译器输出都收集到一个
  程序映像,其中包含执行所需的信息
  执行环境。 (强调我的)
  
  
  [脚注]尽管实际上不同的阶段可能会折叠在一起,但实现方式必须表现得好像这些单独的阶段一样。


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

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

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

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

常见错误消息是Microsoft Visual Studio的error LNK2001error LNK1120error LNK2019和GCC的undefined reference to symbolName。

代码:

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


常见原因包括:


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

关于c++ - 什么是 undefined reference / Unresolved external symbol 错误,如何解决?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26874956/

10-13 07:00