SUMMARY
The linker issues an Unresolved External message if it cannot resolve the address of a function while building a project.
LNK2001: unresolved external symbol '__symbol'
The '__symbol' might be a label, a variable, or a function name.
---------------------------------------------------------------------
下面的链接器行为解释了为什么会发生这种错误,这是一个简单的模型,内部实现可能因编译器而异,但不影响说明。
在编译源文件的时候, 会为每个object module创建一个名称表格以便在不同的object module之间进行符号引用。公共符号表(Public Symbols Table (PST)),它包含着一个对应object module的所有的公共符号,这里的所谓公共符号,即其它module可以引用的符号——比如全局函数和变量。每个object module亦含有一个未解析的符号表格(Unresolved Symbol Table (UST)),这里包含着本module需要解析的一列符号。
如果没有链接错误发生,则链接器会生成一个.map文件,这里列出了“刚刚链接在一起的所有object modules”中的所有公共符号(a combined PST table)。
要生成.map文件:
16位Visual C++使用/MAP:FULL linker option
Visual Workbench->Options menu->project->Linker->category: Miscellaneous, ->place /MAP:FULL in the Other Options edit box
32位Visual C++使用 /MAP:<filename> option,例如在VC4.0中
Build menu->Settings->Linker tab->Category: General->select the Generate Map File check box
图1:
链接器使用工程中所有object和library文件的PST和UST来匹配符号名称。如果链接器在某UST中找到了一个符号,但是在所有的PST文件中都找不到与之对应的项,它就会发出一个 "Unresolved External"错误消息。例如,在图1中,链接其不能解析函数func3()的地址,因此发出了"Unresolved External"错误消息。
经常触发"Unresolved External"错误消息的原因:
Missing Object Files or Libraries Object 或 Libraries 文件缺失
Missing Function Body or Variable 函数体或者变量缺失
Symbol Can't be Found in the Libraries or Object Modules 库或者Object模块中找不到需要的符号
Case Sensitivity 大小写
Name Decoration 命名
A Symbol Is Not Public 某符号非公共
Scoping Problems and Pure Virtual Functions 作用域问题或者纯虚函数问题
Function Inlining 函数内联
Wrong Compiler Options or Mixing Incompatible Libraries 错误的编译器选项
Missing Function Body or Variable 函数体或者变量缺失
如果只提供函数原型,连接器就无法解析任何对此函数的调用,因为它没有定义。结果,该函数就没有被放入combined PST table的表格中。与此类似,如果某外部变量被声明但是没有定义的话,会发生同样的问题。例如:
当使用C++时,确保在类的定义中,为类的每个成员函数都提供函数定义,而非只有原型。如果你在类定义的外部定义了该函数,请确保以如下方式Classname::MemberFunction在函数名前包含类的名称。参见“作用域和纯虚数问题”
当使用C++时,如某个C++程序要调用一个C函数,或者一个C程序要调用C++函数,请使用extern "C"。extern "C"对那些全局的C++函数强制使用C命名方式,这使得它们可以被C程序调用。
void CALLTYPE test(void)
C naming convention
(__cdecl) _test ?test@@YAXXZ
Be aware of compiler switches like /Tp or /Tc that force a file to be compiled as a C (/Tc) or C++ (/Tp) file regardless of the filename extension, or you may get different function names than you expected.
Function prototypes with mismatched parameters can also cause unresolved external errors. Many name-decoration schemes incorporate the parameters of a function into the final decorated function name. Calling a function with parameter types that do not match those in the function definition may also cause this error. This can be a problem in other languages, like FORTRAN, which may also add name decoration to a function.
在下面的例子中,头文件中的函数原型与函数定义不匹配,这会引发问题的。
符号非公共:
只有全局函数和变量会被放在目标文件的PST表中,试图访问如下的类型变量可能会产生问题。
Static functions/variables: 静态函数或者静态变量
静态函数或者静态变量的作用域只在本文件内,如试图从文件外访问这些符号,会引起外部解析错误。例如:
Automatic (function scope) variables: 自动变量(函数内部)
函数内部声明的自动变量只能在函数内部使用!
Global Constants in C++: C++中的全局常量
C++中的全局常量执行静态链接,这与C是不同的。如果你是如在多个C++文件中使用一个全局常量,你就会遇到这个错误,见如下代码示例:
一种折中办法,是将const的初始化放在头文件中,然后需要时包含该头文件即可,可以把它当作函数原型那样去使用。另外一种方法是使它成为非常量,使用的时候进行常量引用即可。
C++中的全局内联函数
。。。
抽象基类
。。。