什么是未定义的引用/未解决的外部符号错误?常见原因是什么?如何修复/预防
C++程序,按以下步骤进行,如 2.2 (学分为Keith Thompson参考):
翻译语法规则的优先顺序由以下阶段规定[见脚注]
- 物理源文件字符以实现定义的方式映射到基本源字符集
(为行尾指示器引入新行字符)如果
必要的[剪报]- 删除紧跟在新行字符后面的反斜杠字符(\)的每个实例,将物理源行拼接到
形成逻辑源行[剪报]- 源文件被分解为预处理标记(2.5)和空格字符序列(包括注释)[剪报]
- 执行预处理指令,展开宏调用,并执行_Pragma一元运算符表达式[剪报]
- 字符文字或字符串文字中的每个源字符集成员,以及每个转义序列和通用字符名
在字符文字或非原始字符串文字中,转换为
执行字符集的对应成员[剪报]- 相邻的字符串文字标记被连接起来
- 分隔标记的空白字符不再有效。每个预处理令牌都转换为一个令牌。(2.7). 这个
对生成的标记进行语法和语义分析并
翻译成一个翻译单位[剪报]- 翻译单元和实例化单元的组合如下:[SNIP]
- 解析所有外部实体引用。库组件链接以满足对中未定义的实体的外部引用
目前的翻译。所有此类翻译器输出都收集到
程序映像,其中包含在其
执行环境。(强调矿山)[footnote]实现的行为必须像这些单独的阶段一样,尽管在实践中不同的阶段可能会折叠在一起
指定的错误发生在编译的最后阶段,通常称为链接。这基本上意味着您将一组实现文件编译成了目标文件或库,现在您想让它们一起工作
假设您在a.cpp中定义了符号a。现在,b.cpp声明了那个符号并使用了它。在链接之前,它只是假设该符号是在某个地方定义的,但它并不关心在哪里。链接阶段负责查找符号并将其正确链接到b.cpp(实际上是链接到使用它的对象或库)
如果您使用的是Microsoft Visual Studio,您将看到项目生成.lib文件。其中包含导出符号表和导入符号表。导入的符号根据链接所针对的库进行解析,导出的符号为使用该.lib(如果有)的库提供
其他编译器/平台也有类似的机制
常见的错误消息有错误LNK2001,错误LNK1120,错误LNK2019对于Microsoft Visual Studio和对于GCC的未定义的引用
守则:
结构X
{
虚拟void foo();
};
结构Y:X
{
void foo(){}
};
结构A
{
虚~A()=0;
};
结构B:A
{
虚拟~B(){}
};
外部INTX;
void foo();
int main()
{
x=0;
foo();
Y;
B B;
}
将使用GCC生成以下错误:
/home/AbiSfw/ccvvuHoX.o:在函数“main”中:
prog.cpp:(.text+0x10):对“x”的未定义引用
prog.cpp:(.text+0x19):对“foo()”的未定义引用
prog.cpp:(.text+0x2d):对'A::~A()'的未定义引用
/home/AbiSfw/ccvvuHoX.o:在函数“B::~B()”中:
prog.cpp:(.text._ZN1BD1Ev[B::~B()]+0xb):对“A::~A()”的未定义引用
/home/AbiSfw/ccvvuHoX.o:在函数“B::~B()”中:
prog.cpp:(.text._ZN1BD0Ev[B::~B()]+0x12):对“A::~A()”的未定义引用
/home/AbiSfw/ccvvuHoX.o:(.rodata.ZTI1Y[typeinfo for Y]+0x8):未定义对“typeinfo for X”的引用
/home/AbiSfw/ccvvuHoX.o:(.rodata.ZTI1B[typeinfo for B]+0x8):对“typeinfo for A”的未定义引用
collect2:ld返回了1个退出状态
以及Microsoft Visual Studio的类似错误:
1>;test2.obj:错误LNK2001:未解析的外部符号“;无效“cdecl foo(无效)”;(?[email protected]@YAXXZ)
1>;test2.obj:错误LNK2001:未解析的外部符号“;INTX";(?[email protected]@3HA)
1>;test2.obj:错误LNK2001:未解析的外部符号“;public:virtual“thiscall A::~A(void)”;(?1A)@@[email protected])
1>;test2.obj:错误LNK2001:未解析的外部符号“;public:virtualvoid“thiscall X::foo(void)”;([email protected]@@UAEXXZ)
1>\test2.exe:致命错误LNK1120:4个未解析的外部
常见原因包括:
- 未能链接到适当的库/对象文件或编译实现文件
- 已声明和未定义的变量或函数
- 类类型成员的常见问题
- 模板实现不可见
- 跨模块/dll错误地导入/导出方法/类。(MSV特定)
- 循环库依赖关系
- 未定义的引用`[email protected]"
- 相互依存的图书馆秩序
- 具有相同名称的多个源文件
- 使用
#pragma时键入错误或未包含.lib扩展名(Microsoft Visual Studio) - 模板朋友的问题
- UNICODE定义不一致
- “失踪”;“外部”;常量变量声明/定义中(仅限C++)
符号在C程序中定义,用于C++代码。