每日日常敲代码,日常看bug,错误提示:

这个错误提示第一次见到,心里表示很难受于是乎google一下:

可以在Linker Tools Error LNK2019中找到该主题的最新版本。

函数'function'中引用的未解析的外部符号'symbol'

链接器找不到symbol函数“ function”中使用的外部符号“ ” 的定义。

有许多问题可能导致此错误。本主题将帮助您确定原因并找到解决方案。

一个符号是编译器使用的函数或全局变量的名称。一个外部符号是用来指的是在不同来源或对象文件中定义的符号的名称。链接器必须为每个编译文件链接到应用程序或DLL时使用的每个函数或全局变量解析或找到外部符号的定义。如果链接器无法在任何链接文件中找到外部符号的匹配定义,则会生成LNK2019。

如果构建中未包含具有符号定义的对象或库文件,则会发生此错误。如果链接器搜索的符号名称与库中的符号名称或定义它的目标文件不匹配,也会发生这种情况。如果调用代码中的名称拼写错误,使用不同的大小写,使用不同的调用约定或指定不同的参数,则会发生这种情况。

使用C ++链接的代码使用名称修饰(也称为名称修改)来编码有关变量或函数类型的额外信息,并在符号名称中调用约定。该修饰名是链接器搜索以解析外部符号的名称。因为类型信息成为符号的修饰名称的一部分,所以如果使用它的外部符号的声明与定义它的符号的声明不匹配,则可能导致LNK2019。为了帮助您找到错误原因,错误消息显示“友好名称”,源代码中使用的名称以及未解析外部符号的修饰名称(括号中)。您不需要知道如何翻译装饰名称以便能够将其与其他装饰名称进行比较。

常见问题

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

  • 包含符号定义的目标文件或库未链接。在Visual Studio中,验证包含该定义的源文件是否已构建并链接为项目的一部分。在命令行上,验证是否已编译包含该定义的源文件,以及生成的目标文件是否包含在要链接的文件列表中。

  • 符号的声明与拼写的定义拼写不同。验证声明和定义中使用的拼写和大小写是否正确,以及使用或调用符号的位置。

  • 使用了一个函数,但参数的类型或数量与函数定义不匹配。函数声明必须与定义匹配。验证函数调用是否与声明匹配,以及声明是否与定义匹配。调用模板函数的代码还必须具有匹配的模板函数声明,其中包含与定义相同的模板参数。有关模板声明不匹配的示例,请参阅示例部分中的示例LNK2019e.cpp。

  • 声明了函数或变量但未定义。这通常意味着头文件中存在声明,但未实现匹配的定义。对于成员函数或静态数据成员,实现必须包括类作用域选择器。有关示例,请参阅缺少函数体或变量。

  • 函数声明和函数定义之间的调用约定是不同的。调用约定(__cdecl,__stdcall,__fastcall,或__vectorcall)被编码为装饰名称的一部分。验证调用约定是否相同。

  • 符号在C文件中定义,但在C ++文件中未使用extern“C”进行声明。编译为C的文件中定义的符号具有与C ++文件中声明的符号不同的装饰名称,除非您使用extern“C”修饰符。验证声明是否与每个符号的编译链接匹配。

    同样,如果在C程序extern "C"中定义将由C程序使用的符号,请在定义中使用。

  • 符号定义为静态,然后在文件外引用。在C ++中,与C不同,全局常量具有static链接。要解决此限制,可以const在头文件中包含初始化并在.cpp文件中包含该头,或者可以使变量非常量并使用常量引用来访问它。

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

  • 构建依赖关系仅在解决方案中定义为项目依赖关系。在早期版本的Visual Studio中,此级别的依赖性已足够。但是,从Visual Studio 2010开始,Visual Studio需要项目到项目的引用。如果您的项目没有项目到项目引用,则可能会收到此链接器错误。添加项目到项目的引用以修复它。

  • 您可以使用Windows应用程序的设置来构建控制台应用程序。如果错误消息类似于函数中引用的未解析的外部符号WinMainfunction_name,则使用/ SUBSYSTEM:CONSOLE而不是/ SUBSYSTEM:WINDOWS进行链接。有关此设置的详细信息,以及有关如何在Visual Studio中设置此属性的说明,请参阅/ SUBSYSTEM(指定子系统)。

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

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

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

  • 您将使用本机wchar_t的代码与不使用本机wchar_t的代码混合在一起。在Visual C ++ 2005中完成的C ++语言一致性工作wchar_t默认情况下是一个本机类型。必须使用/ Zc:wchar_t-编译器选项生成与使用早期版本的Visual C ++编译的库和目标文件兼容的代码。如果并非所有文件都使用相同的/ Zc:wchar_t设置进行编译,则类型引用可能无法解析为兼容类型。wchar_t通过更新所使用的类型或在编译时使用consistent / Zc:wchar_t设置来验证所有库和目标文件中的类型是否兼容。

有关LNK2019的可能原因和解决方案的更多信息,请参阅堆栈溢出问题什么是未定义的参考/未解决的外部符号错误以及如何解决?。

诊断工具

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

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

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

  • UNDNAME实用程序可以显示装饰名称的等效未修饰外部符号。

例子

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

声明符号但未定义

以下示例生成LNK2019,因为已声明外部符号但未定义:

C ++

// LNK2019.cpp
//使用以下
命令   编译:cl / EHsc LNK2019.cpp   // LNK2019预期
extern  char B [100];   // B不可用于链接器
int main(){  B [0] ='';   // LNK2019
}  

这是另一个例子:

C ++

// LNK2019c.cpp
//使用以下
命令   编译:cl / EHsc LNK2019c.cpp   // LNK2019预期
extern  int i;
extern  void g();
void f(){  我++;  G();
}
int main(){}  

如果在构建中的某个文件中定义ig未定义,则链接器将生成LNK2019。您可以通过将包含定义的源代码文件包含在编译中来修复错误。或者,您可以传递包含定义的链接器.obj文件或.lib文件。

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

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

C ++

// LNK2019b.cpp
//使用以下
命令   编译:cl / EHsc LNK2019b.cpp   // LNK2019预期
struct C {  static  int s;
};  //取消注释以下行以修复错误。
// int C :: s;  int main(){  C c;  C :: s = 1;
}  

声明参数与定义不匹配

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

C ++

// LNK2019e.cpp
//使用以下
命令   编译:cl / EHsc LNK2019e.cpp   //预计LNK2019
#include <iostream>
使用 命名空间 std;  template < class T> 类
测试{  // operator <<声明与下面的定义不匹配:   friend ostream&operator <<(ostream&,Test&);  //要修复,请使用以下内容替换上面的行:   // template <typename T> friend ostream&operator <<(ostream&,Test <T>&);
};  template < typename T>
ostream&operator <<(ostream&os,Test <T>&tt){  return os;
}  int main(){  测试< int > t;  cout << “测试:” << t << endl;   // LNK2019未解析外部
}  

wchar_t类型定义不一致

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

C ++

// LNK2019g.cpp
//编译:cl / EHsc / LD LNK2019g.cpp
#include “windows.h”
// WCHAR解析为wchar_t
__declspec(dllexport)void func(WCHAR *){}  

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

C ++

// LNK2019h.cpp
//使用以下
命令   编译:cl / EHsc LNK2019h LNK2019g.lib   // LNK2019期望
__declspec(dllimport)void func(unsigned  short *);  int main(){  FUNC(0);
}  

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


经过细心察看发现函数名的参数与我在头函数定义的参数类型不匹配,一个bug已经消除,新的bug又来了...

Mr.J--C语言学习Errors:LNK2019相关推荐

  1. c语言行列坐标是先行后j,C语言学习之行列操作

    C语言学习之队列操作 本文件为队列操作的接口: /*queue.h*/ #ifndef _SEQQUEUE_H_ #define _SEQQUEUE_H_ #define QUEUE_MAX 15 t ...

  2. go语言学习初探(二)基础语法

    变量声明 var v1 int var v2 string var v3 [10]int var v4 []int var v5 struct {f int } var v6 *int var v7 ...

  3. 【Go语言 · 学习笔记】

    文章目录 Go语言 · 学习笔记 一.Go包管理 1. 什么是Go语言中的包 2. 包的命名 3. main包 4. 导入包 5. 远程包导入 6. 命名导入 7. 包的init函数 二.Go开发工具 ...

  4. R语言学习手记 (1)

    R语言学习手记 (1) 经管的会计和财管都会学数据统计与分析R语言这门课,加上我也有点兴趣,就提前选了这门课,以下的笔记由老师上课的PPT.<R语言编程艺术>和<R语言数据科学> ...

  5. C语言学习趣事_之_大数运算_加法

    C语言学习趣事_大数运算_之加法 1.引子    在C语言中,因为预定义的自然数类型的大小是有上下限度的,这就决定了在进行数的运算的时候,必然受到限制,同时因为C语言是最接近汇编的一种程序设计语言,并 ...

  6. Python语言学习:Python常用自带库(imageio、pickle)简介、使用方法之详细攻略

    Python语言学习:Python常用自带库(imageio.pickle)简介.使用方法之详细攻略 目录 imageio简介及其常见使用方法 pickle简介及其常见使用方法 简介 使用方法 简介及 ...

  7. c 语言学习:基本操作,数组,字符串,指针

    文章目录 基本操作 判断闰年平年 倒序输出五位数 赋值运算 用条件表达式求三个数的最大值 测试int,float,char类型在本机所占的字节数 单个字符的输入getchar() 使用*抑制符跳过输入 ...

  8. C语言学习之用*打印菱形

    C语言学习之用*打印菱形 #include <stdio.h> int main(){int i,j,k;//定义变量for(i=0;i<=3;i++){ //控制菱形的前三行for ...

  9. 12天学好C语言——记录我的C语言学习之路(Day 12)

    12天学好C语言--记录我的C语言学习之路 Day 12: 进入最后一天的学习,用这样一个程序来综合考量指针和字符串的关系,写完这个程序,你对字符串和指针的理解应该就不错了. //输入一个字符串,内有 ...

最新文章

  1. 【编译原理】关于解释器和编译器的讨论
  2. 虚拟化方案应用场景及优劣
  3. linux的/etc/hosts的作用
  4. Spring注意事项(各部分理解)
  5. Letters Removing CodeForces - 899F (线段树维护序列)
  6. C# (逻辑与) ||(逻辑或)优先级辨析
  7. 信息学奥赛C++语言:幸运奶牛
  8. oracle中dblink怎么用,Oracle中建立了dblink怎么使用
  9. SIM: 基于搜索的超长行为序列上的用户兴趣建模
  10. 敏捷开发免费管理工具——火星人预览之六:我的空间,我的通知
  11. IntelliJ中可能的东西在Eclipse中是不可能的?
  12. 设计模式--工厂方法模式
  13. html点击标签c,html - 标签并以html形式输入点击其他提交按钮(所有浏览器) - 堆栈内存溢出...
  14. width:100%以什么为基准的测试
  15. 关于Redis在windows上运行及fork函数问题
  16. UE4/UE5 虚幻引擎,Light光照系列(一)
  17. jQuery Ajax async=false异步改为同步时,导致浏览器假死的处理方法
  18. 桂林理工研究生院计算机软件工程,2019桂林理工大学硕士研究生复试细则之软件工程...
  19. 二叉树线索化(C语言)
  20. 重写yolo数据加载模块

热门文章

  1. PyImageSearch新出教程:Dlib多目标跟踪(附下载地址)
  2. python 基础 - 开发环境搭建
  3. nacos当配置中心读取其他配置文件_SpringBoot+Nacos实现配置中心
  4. 收藏 | Pytorch nn.Transformer的mask理解
  5. R-CNN 物体检测第一弹
  6. caffe 图片数据的转换成lmdb和数据集均值(转)
  7. 泛海三江手动控制盘怎么设置_消防自动控制、手动控制和机械应急操作-区别及应用...
  8. 西安工程大学c语言试卷,知到_大学应用写作_单元测试答案知到C语言程序设计(西安工程大学)见面课答案...
  9. JDBC基本知识总结概括及8个阶段优化过程:
  10. 标题文字超出2行 则隐藏后面显示省略号