比较权威的解释可参考微软官方文档https://docs.microsoft.com/en-us/previous-versions/799kze2z(v=vs.140)?redirectedfrom=MSDN

我的开发环境是Visual Studio 2013 Community,使用语言是C++,遇到这个问题时正在自己做DLL自己调用,在调用时出现这个错误。


这里简述官方文档中列举的常见发生原因,这里结合我的经历做一些记录,加粗部分为原文内容:

  • 一、The object file or library that contains the definition of the symbol is not linked.(包含符号定义的目标文件或库文件没有被链接。)

解决方法是检查是否正确指定了用到的.lib文件或者.dll文件等,它们是否被编译完成(是否存在),还要注意版本是否一致。可以检查以下三个目录中是否配置了所需要的文件:

  1. 项目、属性、配置属性、VC++目录、包含目录:此处用于放置需要调用的外部的头文件夹。

  2. 项目、属性、配置属性、VC++目录、库目录:此处用于放置需要调用的外部lib文件夹。

  3. 项目、属性、配置属性、链接器、输入、附加依赖项:此处用于记录需要调用的外部lib文件具体文件名。

以上三个目录是项目全局设定方法,可以用局部目录如配置属性中的C/C++目录项代替,依具体使用需求而定。

说起来好像在质疑大家配置各项选项的能力,但是确实有可能发生这种情况。我见过以下三种情况:

  1. 写DLL和调用DLL的项目分别使用了不同的平台,x64和x86混用。可以搭配出现“无法打开文件”、“模块计算机类型与目标计算机类型冲突”等问题

  2. DLL的输出目录改到了其他位置B,在修改前的默认路径A下生成过一次,调用DLL的项目指向了修改前的默认路径A下的文件。发生这种情况的时候,可以看到部分符号(函数)不显示错误,而另一部分符号无论怎么改都是错的,这种错误还常常发生在最后写的一部分内容。

  3. release和debug版本没对应好,用debug模式开发项目,却把调用DLL的项目指向了以前生成的release版本的DLL,生成的DLL都是debug版本,下游项目完全看不到更新,却想调用新的内容,就出现错误,跟第二个一样,发生这种情况的时候,可以看到部分符号(函数)是正确的,而另一部分符号无论怎么改都是错的,这种错误常常发生在最后写的一部分内容。

  • 二、The declaration of the symbol is not spelled the same as the definition of the symbol.(符号在声明和定义时拼写不一致)

在.h文件和.cpp文件中是否拼写一致,另外是否与调用时保持一致。

  • 三、A function is used but the type or number of the parameters do not match the function definition.(调用函数时参数的类型和数量与定义不一致)

我见过这种错误,它可能与“函数不接受n个参数”或类似的错误同时出现。

  • 四、A function or variable is declared but not defined.(函数或变量只有声明没有定义)

在头文件中指给出了一个声明,后面却没有给出相应的定义实现。常见于类的成员函数、静态变量等。有可能是写单例模式时在源文件中函数定义处笔误忘记加类名,如base* base::getInstance错误写成base* getInstance,这使getInstance称为全局函数,并非类成员函数的定义。也有可能写构造函数析构函数想给一个空的函数体,却错误的只写了一个分号,如class base{ base(); }; 改成一对大括号即可,如class base{ base(){} }; 也有可能是使用了内联函数inline,某些情况下加入inline会直接导致无法解析的外部符号,去掉即可通过。

  • 五、The calling convention is different between the function declaration and the function definition.(函数声明和定义时的调用约定不一致)

调用约定__cdecl,__stdcall,__fastcall,__vectorcall在函数的声明和定义处不一致,在错误提示处开头就有显示。

  • 六、A symbol is defined in a C file, but declared without using extern "C" in a C++ file.(在C文件中定义的符号在C++文件中声明时没有使用extern "C"

相似地,在C++文件中定义的符号,想在C项目中使用,应该在定义的地方加extern "C"

  • 七、A symbol is defined as static and then later referenced outside the file.(下面是此段原文,我解释不了(╥﹏╥) )

In C++, unlike C, global constants have static linkage. To get around this limitation, you can include the const initializations in a header file and include that header in your .cpp files, or you can make the variable non-constant and use a constant reference to access it.

  • 八、A static member of a class is not defined. (静态成员没有定义)

一个典型的例子是使用单例模式时忘记在类外给静态变量instance实例进行初始化。

  • 九、A build dependency is only defined as a project dependency in the solution.(有项目依赖时不能仅建立build依赖,需要建立project-to-project水平上的依赖)

没用到,具体见官方文档https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2015/ide/managing-references-in-a-project?view=vs-2015&redirectedfrom=MSDN

  • 十、You build a console application by using settings for a Windows application. (想建立一个控制台应用程序,却建立了一个窗口应用程序)

如果提示错误是类似“unresolved external symbol WinMain referenced in function”,可以尝试把/SUBSYSTEM:WINDOWS替换成/SUBSYSTEM:CONSOLE,在项目、属性、配置属性、链接器、系统、子系统。emmm这个问题比较严重,建议重新建立。

  • 十一、You use different compiler options for function inlining in different source files.(不同源文件中的内联函数用不用的编译器选项编译)

看起来这种情况也许是,如果有多个从源代码编译的依赖库,要保证编译时编译器版本和选项一致。

  • 十二、You use automatic variables outside their scope. (在作用域外使用了自动变量)

  • 十三、You call instrinsic functions or pass argument types to intrinsic functions that are not supported on your target architecture.(使用目标架构中没有的内部函数)

比如想使用Intel Advanced Vector Extensions 2 instructions里的内部函数,却没有指定/ARCH:AVX2,内部函数就当作了外部函数,所以找不到。(没用过,翻译的)

  • 十四、You mix code that uses native wchar_t with code that doesn't.

看到网上一些帖子提到字符集不一致导致无法解析的外部符号,在项目、属性、配置属性、常规、项目默认值、字符集,看看几个项目是否一致。


这还不是全部,微软推荐了这个网站https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix

从上面一条一条来看,无非是配置设错了,或者代码漏写了,调用的程序看不到它。

如果调用的内容是别人的发行版而且其他人可以用,那么就是自己配置错了,古话说得好,重启解决90%的问题,重装解决99%的问题,再从零开始看一遍配置,在心里模拟一遍项目的建立。可以对照第一、五、六、九、十、十一、十三、十四条。

如果是自己写的依赖库以前能用,而现在不能用:若刚刚修改了配置,参照上一条;如果没有修改配置,那就是代码问题。可以对照第二、三、四、七、八、十二条。稳住!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐