一般链接错误都是因为包含头文件与lib库不匹配(无导出函数、lib库的release debug版本混乱、库引用的优先级、编译器设置mt/mtd等等)造成的。
错误 LNK2019 无法解析的外部符号 "int __cdecl pipe_server(void)" (?pipe_server@@YAHXZ),该符号在函数 WinMain 中被引用
首先因为是c工程 引用了c++代码,混编时会出现这种问题,因为我就一个小工程,就把c变成了cpp后缀。很多错误消失了,但是还是出现这种错误,原来是call的方式不对 应该以c的方式call
#ifdef __cplusplus extern "C" { #endif int pipe_server(VOID); #ifdef __cplusplus } #endif
此时报错:
错误 LNK2019 无法解析的外部符号 pipe_server,该符号在函数 WinMain 中被引用
因为我没有引用外部库,所以排除lib库的因素,但是这个错误确实是链接的问题,找到定义了却找不到实现
想编译.h对应的cpp文件看看,但是发现对应的,发现右键编译是灰色的。问题找到了,原因是创建时只想创建一个.h头文件,随着需求增加就把一些实现放进去了,仅仅在该文件上重命名成了.cpp,vs并没有随着重命名更改文件的属性。
右键该cpp文件,-属性-常规 -项类型 “C/C++ 标头” 一般的应该是“C/C++ 编译器”,更改之后顺利编译通过。 vs2015原来还记录这个,感觉像是vs的一个bug。
参考
----------------------------------------------------------------------------------------------------------------------------
http://www.cnblogs.com/hiloves/p/4678848.html
“error LNK2019: 无法解析的外部符号”之分析
最近在用VS 2008开发,初学遇到不少问题,最头疼的问题之一就是:LNK2019。
百度一下讲的并不够全面,反正都没解决我的问题。
error LNK2019问题在VC 6.0中是error LNK2001: unresolved external symbol问题,可能错误号改了。
编译时出现类似这样的错误:Dlgcode.obj : error LNK2019: 无法解析的外部符号 _readRegmark,该符号在函数 _AboutDlgProc@16 中被引用。这种错误的本质是链接器无法在已编译的obj、lib或dll文件中找到函数定义。
1、这是百度找到的方法:http://jingyan.baidu.com/article/4d58d54135d7a79dd4e9c0ad.html。就是有头文件(有了函数声明)却没有lib。一般出现于你使用了第三方提供的库,下载了头文件却忘了载库文件,或库文件忘记放到相应的目录下了。
2、你自己写的函数声明的头文件也写了函数定义的cpp文件,却依然出现LNK2019错误。可能原因:忘记将这两个文件加入工程了。一般出现于用Visual Studio和记事本(或UltraEdit)混合开发过程,你用记事本include了相应的头文件,却忘了在Visual Studio的工程中加入它们了。也可能出现于在解决方案的开发过程,在解决方案下的某个工程中加入了它们却忘了在其他工程中加入,我只接触过VC 6和VS 2008,中间好多年没用过新版本VS,到2008时突然发现怎么多了个“解决方案”,“解决方案”下面还可以放好多工程,于是经常在一个工程中写了共享的源代码,却忘了在别的工程中加入它们。这个问题类似于第1个,不同的是这个库是你自己提供的,但没有把它交给VS 2008编译出来。
3、你自己写的函数声明的头文件也写了函数定义的cpp文件也加入工程了而且你很确定函数体肯定是在这个库文件中,却依然出现LNK2019错误。可能原因:C语言和C++语言混编,因为C++支持函数重载所以C++编译器生成的库文件中的函数名会面目全非,例如C编译器会生成 _readRegmark 这个函数名,而C++编译器则生成了"void __cdecl readRegmark(char *)" (?readRegmark@@YAXPAD@Z)这么个函数名。当你的函数是用C语言写的,VS编译器会按C语言规则编译,但链接器却不知道还傻傻的用C++规则的函数名去找结果就找不到了,而你还百般肯定TM的不就在这个库中吗你个睁眼瞎。解决:在C语言的头文件中加入
#ifdef __cplusplus
extern "C" {
#endif
void readRegmark(char *regmark); //这里写函数声明
#ifdef __cplusplus
}
#endif
给链接器提示这个函数是C语言的,别TM找错了。
4、这是我百度来的,姑且也放进来。http://blog.csdn.net/jtop0/article/details/5779782。模板声明和实现要放在同一文件夹中。
5、也是百度来的。http://www.programlife.net/error-lnk2019.html。内联函数定义在头文件中。
6、百度的。http://jingyan.baidu.com/article/d621e8da0d7c022864913f40.html。错误的工程类型造成的。
7、貌似还有不尽之处。http://www.douban.com/note/65638800/。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
https://jingyan.baidu.com/article/d621e8da0d7c022864913f40.html
-
编译时出现如下错误:
1>MSVCRTD.lib(crtexe.obj) : error LNK2019: 无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用
-
右击项目,打开“属性”页
-
更改上图红色框内容为/subsystem:windows。如果是刚开始默认的是/subsystem:windows
则改为/subsytem:console
-
再次编译即过通过测试,运行结果截图如下
----------------------------------------------------------------------------------------------------------------------------------------------------
https://www.douban.com/note/65638800/
学习VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于编程者来说,最好改的错误莫过于编译错误,而一般说来发生连接错误时,编译都已通过。产生连接错误的原因非常多,尤其LNK2001错误,常常使人不明其所以然。如果不深入地学习和理解VC++,要想改正连接错误LNK2001非常困难。
初学者在学习VC++的过程中,遇到的LNK2001错误的错误消息主要为:
unresolved external symbol “symbol”(不确定的外部“符号”)。
如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或标签,将产生此错误消息。一般来说,发生错误的原因有两个:一是所引用的函数、变量不存在、拼写不正确或者使用错误;其次可能使用了不同版本的连接库。
以下是可能产生LNK2001错误的原因:
一.由于编码错误导致的LNK2001
1.不相匹配的程序代码或模块定义(.DEF)文件能导致LNK2001。例如, 如果在C++源文件内声明了一变量“var1”,却试图在另一文件内以变量“VAR1”访问该变量,将发生该错误。
2.如果使用的内联函数是在.CPP文件内定义的,而不是在头文件内定义将导致LNK2001错误。
3.调用函数时如果所用的参数类型同函数声明时的类型不符将会产生LNK2001。
4.试图从基类的构造函数或析构函数中调用虚拟函数时将会导致LNK2001。
5.要注意函数和变量的可公用性,只有全局变量、函数是可公用的。静态函数和静态变量具有相同的使用范围限制。当试图从文件外部访问任何没有在该文件内声明的静态变量时将导致编译错误或LNK2001。
函数内声明的变量(局部变量) 只能在该函数的范围内使用。
C++ 的全局常量只有静态连接性能。这不同于C,如果试图在C++的多个文件内使用全局变量也会产生LNK2001错误。一种解决的方法是需要时在头文件中加入该常量的初始化代码,并在.CPP文件中包含该头文件;另一种方法是使用时给该变量赋以常数。
二.由于编译和链接的设置而造成的LNK2001
1.如果编译时使用的是/NOD(/NODEFAULTLIB)选项,程序所需要的运行库和MFC库在连接时由编译器写入目标文件模块, 但除非在文件中明确包含这些库名,否则这些库不会被链接进工程文件。在这种情况下使用/NOD将导致错误LNK2001。
2.如果没有为wWinMainCRTStartup设定程序入口,在使用Unicode和MFC时将得到“unresolved external on _WinMain@16”的LNK2001错误信息。
3.使用/MD选项编译时,既然所有的运行库都被保留在动态链接库之内,源文件中对“func”的引用,在目标文件里即对“__imp__func”
的引用。如果试图使用静态库LIBC.LIB或LIBCMT.LIB进行连接,将在__imp__func上发生LNK2001;如果不使用/MD选项编
译,在使用MSVCxx.LIB连接时也会发生LNK2001。
4.使用/ML选项编译时,如用LIBCMT.LIB链接会在_errno上发生LNK2001。
5.当编译调试版的应用程序时,如果采用发行版模态库进行连接也会产生LNK2001;同样,使用调试版模态库连接发行版应用程序时也会产生相同的问题。
6.不同版本的库和编译器的混合使用也能产生问题,因为新版的库里可能包含早先的版本没有的符号和说明。
编程时打开了函数内联(/Ob1或/Ob2),但是在描述该函数的相应头文件里却关闭了函数内联(没有inline关键字),这时将得到该错误信息。为避免该问题的发生,应该在相应的头文件中用inline关键字标志内联函数。
8.不正确的/SUBSYSTEM或/ENTRY设置也能导致LNK2001。
解决方法:
解决外部符号错误:_main,_WinMain@16,__beginthreadex
在创建MFC项目时, 不使用MFC AppWizard向导, 就会在编译时产生很多连接错误, 如error LNK2001错误, 典型的错误提示有:
libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@
msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
1. Windows子系统设置错误, 提示:
libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Windows项目要使用Windows子系统, 而不是Console, 可以这样设置:
[Project] --> [Settings] --> 选择"Link"属性页, 在Project Options中将/subsystem:console改成/subsystem:windows
2. Console子系统设置错误, 提示:
LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@控制台项目要使用Console子系统, 而不是Windows, 设置:
[Project] --> [Settings] --> 选择"Link"属性页
3. 程序入口设置错误, 提示:
msvcrtd.lib(crtexew.obj)
: error LNK2001: unresolved external symbol _WinMain@通常,
MFC项目的程序入口函数是WinMain, 如果编译项目的Unicode版本, 程序入口必须改为wWinMainCRTStartup,
所以需要重新设置程序入口:
[Project] --> [Settings] --> 选择"Link"属性页, 在Category中选择Output, 再在Entry-point symbol中填入wWinMainCRTStartup, 即可
4. 线程运行时库设置错误, 提示:nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex这是因为MFC要使用多线程时库, 需要更改设置:
[Project]
--> [Settings] --> 选择"C/C++"属性页, 在Category中选择Code
Generation,再在Use run-time library中选择Debug Multithreaded或者multithreaded
其中, Single-Threaded 单线程静态链接库(release版本)
Multithreaded 多线程静态链接库(release版本)
multithreaded DLL 多线程动态链接库(release版本)
Debug Single-Threaded 单线程静态链接库(debug版本)
Debug Multithreaded 多线程静态链接库(debug版本) )
Debug Multithreaded DLL 多线程动态链接库(debug版本)
单线程: 不需要多线程调用时, 多用在DOS环境下
多线程: 可以并发运行
静态库: 直接将库与程序Link, 可以脱离MFC库运行
动态库: 需要相应的DLL动态库, 程序才能运行
release版本: 正式发布时使用
debug版本: 调试阶段使用
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
http://www.roboby.com/%e6%80%aa%e5%bc%82%e7%9a%84-linker-error-lnk2019.html
怪异的 Linker Error LNK2019
今天碰到一个很奇怪的链接错误:LNK2019.
通常碰到这个问题,都是因为只有申明没有实现导致的。要么是lib库没链接进来,要么是工程中只有头文件,没有添加其对应的cpp文件,导致只有申明没有定义。
而今天碰到的奇葩问题是,同一个工程里,h文件及其对应的cpp文件都在工程中,而且通过h文件中的函数申明按F12键转到定义也没问题,即,申明和定义都没问题。
最后猛然发现, 头文件中对一个类型的预定义出问题了!本来此类型是个struct,结果预定义成了class!
这就很好理解了:由于一个类在头文件中可能要用到另一个类型,又不想在头文件中包含另一个类型的头文件,或者因为循环引用的问题,没法在这里包含另一个类的头文件,则我们在这里先预定义这个类的申明,这样,就可以在头文件中用这个类来申明变量(只能申明指针变量,而不能使用实体,因为实体会真正导致使用另一个类的类定义),然后在cpp文件中才真正包含另一个类的头文件,并为这个预先定义的指针变量new一个实体对象。
那么问题来了,如果在对另一个类做预定义时本来是class,却定义成了struct,或者本来是struct,却错误的定义成了class,那么对于头文件,编译的时候使用的是预定义符号,而cpp文件中由于包含了另一个类的头文件,使用的是真正的申明和定义。
这种错误目前几乎所有编译器都会放过去的,但是链接的时候,目前看gcc编译器是放过去了,但微软的vc链接器包KNK2019链接错误!
这个问题,实在是因为黔驴技穷,耗费了好几个小时后没辙了,所以才打开错误警告才发现的。