LNK2019 unresolved external symbol symbol referenced in function

  • 未解析的外部符号' 在功能' 函数 '中引用的 “符号

函数的已编译代码对symbol进行引用或调用,但是链接器在要链接的任何库或目标文件中都找不到符号定义。

此错误消息后跟致命错误LNK1120。要修复错误LNK1120,必须首先修复所有LNK2001和LNK2019错误。

可能的原因

有很多方法可以解决此错误。所有这些都涉及对链接器无法解析的函数或变量的引用,也无法为其找到定义。编译器可以识别没有声明符号的时间,但是不能识别没有定义符号的时间。那是因为定义可能在不同的源文件或库中。如果引用了一个符号但从未定义过,则链接器会生成未解决的外部符号错误。

这是导致LNK2019的一些常见问题:

包含符号定义的源文件未编译

在Visual Studio中,确保定义符号的源文件已作为项目的一部分进行编译。检查中间版本输出目录中是否有匹配的.obj文件。如果未编译源文件,请在解决方案资源管理器中右键单击该文件,然后选择“ 属性”以检查文件的属性。在配置属性 > 常规页应显示的项目类型C / C ++编译器。在命令行上,确保已编译包含定义的源文件。

包含符号定义的目标文件或库未链接

在Visual Studio中,确保包含符号定义的目标文件或库已链接为项目的一部分。在命令行上,确保要链接的文件列表包含目标文件或库。

该符号的声明与该符号的定义拼写不同

验证在声明和定义中以及在使用或调用该符号的任何位置均使用正确的拼写和大写字母。

使用了函数,但参数的类型或数量与函数定义不匹配

函数声明必须与定义匹配。确保函数调用与声明匹配,并且声明与定义匹配。调用模板函数的代码还必须具有匹配的模板函数声明,这些声明包括与定义相同的模板参数。有关模板声明不匹配的示例,请参见“示例”部分中的示例LNK2019e.cpp。

函数或变量已声明但未定义

当头文件中存在声明但未实现匹配的定义时,可能会发生LNK2019。对于成员函数或静态数据成员,实现必须包括类范围选择器。有关示例,请参见缺少函数体或变量

函数声明和函数定义之间的调用约定不同

调用约定(__cdecl__stdcall__fastcall,或__vectorcall)被编码为装饰名称的一部分。确保调用约定相同。

符号在C文件中定义,但在C ++文件中不使用外部“ C”进行声明

除非使用extern“ C”修饰符,否则编译为C的文件中定义的符号的修饰名称与C ++文件中声明的符号不同。确保声明与每个符号的编译链接相匹配。同样,如果您在C ++文件extern "C"中定义将由C程序使用的符号,请在定义中使用。

符号定义为静态,然后在文件外部引用

在C ++中,与C不同,全局常量具有static链接。要解决此限制,可以将const初始化包含在头文件中,并将该头包含在.cpp文件中,或者可以使变量为非常量,并使用常量引用对其进行访问。

未定义类的静态成员

静态类成员必须具有唯一的定义,否则它将违反一定义规则。必须使用一个完全限定的名称在一个源文件中定义无法内联定义的静态类成员。如果根本没有定义,则链接器将生成LNK2019。

在解决方案中,构建依赖关系仅定义为项目依赖关系

在Visual Studio的早期版本中,这种级别的依赖关系就足够了。但是,从Visual Studio 2010开始,Visual Studio需要项目之间的引用。如果您的项目没有项目间参考,则可能会收到此链接器错误。添加项目间引用以进行修复。

入口点未定义

应用程序代码必须定义适当的入口点:mainwmain用于控制台应用程序,WinMainwWinMain用于Windows应用程序。有关更多信息,请参见main函数和命令行参数WinMain函数。要使用自定义入口点,请指定/ ENTRY(入口点符号)链接器选项。

您通过使用Windows应用程序的设置来构建控制台应用程序

如果错误消息类似于函数 function_name中引用的无法解析的外部符号WinMain,请使用/ SUBSYSTEM:CONSOLE而不是/ SUBSYSTEM:WINDOWS进行链接。有关此设置的更多信息,以及有关如何在Visual Studio中设置此属性的说明,请参见/ SUBSYSTEM(指定子系统)

链接到您的代码的库和目标文件必须按照与您的代码相同的体系结构进行编译。确保为与项目相同的体系结构编译项目引用的库。确保“ / LIBPATH”或“ 其他库目录”属性指向为正确体系结构构建的库。

您使用不同的编译器选项在不同的源文件中进行函数内联

使用.cpp文件中定义的内联函数并在不同的源文件中混合使用内联函数的编译器选项,可能会导致LNK2019。有关更多信息,请参见函数内联问题

您在其范围之外使用自动变量

自动(函数范围)变量只能在该函数的范围内使用。这些变量不能extern在其他源文件中声明和使用。有关示例,请参见自动(函数作用域)变量

您调用内部函数或将参数类型传递给目标体系结构不支持的内部函数

例如,如果您使用AVX2内部函数,但未指定/ ARCH:AVX2编译器选项,则编译器会假定内部函数是外部函数。编译器会生成对与内部函数同名的外部符号的调用,而不是生成内联指令。当链接器尝试查找此缺失函数的定义时,它将生成LNK2019。确保仅使用目标体系结构支持的内部函数和类型。

您将使用本机wchar_t的代码与未使用本机代码的代码混合

默认情况下,在Visual Studio 2005中完成的C ++语言一致性工作使wchar_t成为本机类型。如果不是使用相同的/ Zc:wchar_t设置编译了所有文件,则类型引用可能无法解析为兼容类型。确保所有库文件和目标文件中的wchar_t类型都兼容。从wchar_t typedef 更新,或在编译时使用一致的/ Zc:wchar_t设置。

第三方库问题和Vcpkg

如果在尝试将第三方库配置为构建的一部分时看到此错误,请考虑使用Visual C ++程序包管理器Vcpkg来安装和构建该库。Vcpkg支持大量且不断增长的第三方库。它将成功构建所需的所有配置属性和依赖项设置为项目的一部分。有关更多信息,请参见相关的Visual C ++博客文章。

诊断工具

有时很难说出链接器为什么找不到特定的符号定义。通常的问题是,您的构建中没有包含包含定义的代码。或者,构建选项为外部符号创建了不同的修饰名称。有多种工具和选项可帮助您诊断LNK2019错误。

例子

以下是几个导致LNK2019错误的代码示例,以及有关如何修复该错误的信息。

符号已声明但未定义

在此示例中,声明了但未定义外部变量:

// LNK2019.cpp
// Compile by using: cl /EHsc /W4 LNK2019.cpp
// LNK2019 expected
extern char B[100];   // B isn't available to the linker
int main() {
   B[0] = ' ';   // LNK2019
}

这是另一个示例,其中变量和函数被声明为,extern但未提供定义:

// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
   i++;
   g();
}
int main() {}

除非ig在包括在生成的文件中的一个定义,链接器产生LNK2019。您可以通过将包含定义的源代码文件作为编译的一部分来修复错误。或者,您可以将包含定义的.obj文件或.lib文件传递给链接器。

声明了静态数据成员但未定义

当声明但未定义静态数据成员时,也会发生LNK2019。以下示例生成LNK2019,并显示如何修复它。

// LNK2019b.cpp
// Compile by using: cl /EHsc LNK2019b.cpp
// LNK2019 expected
struct C {
   static int s;
};

// Uncomment the following line to fix the error.
// int C::s;

int main() {
   C c;
   C::s = 1;
}

声明参数与定义不匹配

调用模板函数的代码必须具有匹配的模板函数声明。声明必须包含与定义相同的模板参数。以下示例在用户定义的运算符上生成LNK2019,并显示如何修复它。

// LNK2019e.cpp
// compile by using: cl /EHsc LNK2019e.cpp
// LNK2019 expected
#include <iostream>
using namespace std;

template<class T> class
Test {
   // The operator<< declaration doesn't match the definition below:
   friend ostream& operator<<(ostream&, Test&);
   // To fix, replace the line above with the following:
   // template<typename T> friend ostream& operator<<(ostream&, Test<T>&);
};

template<typename T>
ostream& operator<<(ostream& os, Test<T>& tt) {
   return os;
}

int main() {
   Test<int> t;
   cout << "Test: " << t << endl;   // LNK2019 unresolved external
}

wchar_t类型定义不一致

本示例创建一个DLL,该DLL具有使用的导出,WCHAR解析为wchar_t

// LNK2019g.cpp
// compile with: cl /EHsc /LD LNK2019g.cpp
#include "windows.h"
// WCHAR resolves to wchar_t
__declspec(dllexport) void func(WCHAR*) {}

下一个示例使用上一个示例中的DLL,并生成LNK2019,因为类型unsigned short*和类型WCHAR*不相同。

// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);

int main() {
   func(0);
}

要解决此错误,请更改unsigned shortwchar_tWCHAR,或使用/ Zc:wchar_t-编译LNK2019g.cpp

  • / VERBOSE链接器选项可以帮助你确定哪些文件链接引用。此选项可帮助您验证包含符号定义的文件是否包含在您的构建中。

  • DUMPBIN实用程序的/ EXPORTS/ SYMBOLS选项可以帮助您发现.dll和对象或库文件中定义了哪些符号。确保导出的修饰名称与链接器搜索的修饰名称匹配。

  • UNDNAME工具可以告诉你一个名字装饰相当于未修饰的外部符号。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值