关于MFC库和CRT库冲突的分析
nafxcwd.lib(dllmodul.obj): error LNK2005: _DllMain@12 already defined in LIBCMTD.lib(dllmain.obj)
nafxcwd.lib(afxmem.obj): error LNK2005: "void * __cdecl operator new(unsigned int)"(??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)
nafxcwd.lib(afxmem.obj): error LNK2005: "void __cdecl operator delete(void *)"(??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj)
nafxcwd.lib(afxmem.obj): error LNK2005: "void __cdecl operator delete[](void *)"(??_V@YAXPAX@Z) already defined in LIBCMTD.lib(delete2.obj)
首先我们来认识下这些错误中提示的信息:
nafxcwd.lib,MFC静态链接库,调试版。(发布版是nafxcw.lib)
LIBCMTD.lib,多线程版的CRT库。
DLLMain函数,在dllmodul.cpp和dllmain.cpp中都有定义。
new、delete、delete[],CRT库中有一套标准实现,但是MFC中均重新实现了一遍。
那么上面的错误的意思即是,已经链接过LIBCMTD.lib,再链接nafxcwd.lib即会报重复定义的错误。
对于MFC工程中的DllMain,new, delete函数要求先链接MFC库。而通过上面的错误信息显示,工程是先链接的LIBCMTD.lib,才会出错。
|
版 本 |
类 型 |
使用的library |
被忽略的library |
备注 |
|
R Release |
单线程 |
libc.lib |
libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib |
|
|
多线程 |
libcmt.lib |
libc.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib |
MTd |
|
|
使用DLL的多线程 |
msvcrt.lib |
libc.lib, libcmt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib |
MDd |
|
|
D Debug |
单线程 |
libcd.lib |
libc.lib, libcmt.lib, msvcrt.lib, libcmtd.lib, msvcrtd.lib |
|
|
多线程 |
libcmtd.lib |
libc.lib, libcmt.lib, msvcrt.lib, libcmtd.lib, msvcrtd.lib |
MT |
|
|
使用DLL的多线程 |
msvcrtd.lib |
libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib |
MD |
然后,我们来看一下工程的链接顺序。
在工程Properties->Liker->General->Show Progress->For Libraries Searched (如果想看更详细的信息可选Displayall progress messages)。
会显示如下信息:
Searching libraries
Searching C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\lib\LIBCMTD.lib:
Searching C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\lib\OLDNAMES.lib:
Searching C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\lib\nafxcwd.lib:
nafxcwd.lib(dllmodul.obj): error LNK2005: _DllMain@12 already defined in LIBCMTD.lib(dllmain.obj)
nafxcwd.lib(afxmem.obj): error LNK2005: "void * __cdecl operator new(unsigned int)"(??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)
nafxcwd.lib(afxmem.obj): error LNK2005: "void __cdecl operator delete(void *)"(??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj)
nafxcwd.lib(afxmem.obj): error LNK2005: "void __cdecl operator delete[](void *)"(??_V@YAXPAX@Z) already defined in LIBCMTD.lib(delete2.obj)
Searching C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.0A\lib\kernel32.lib:
Searching C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.0A\lib\user32.lib:
Searching C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.0A\lib\gdi32.lib:
Searching C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.0A\lib\msimg32.lib:
从上面搜索链接库的顺序,就可以看出是先链接LIBCMTD.lib的,然后再链接nafxcwd.lib时就报错。
再次,我们打开*.vcproj工程文件,找到类似下面的信息
<ItemGroup>
<ClCompile Include="CSI.c"/>
<ClCompileInclude="Log.cpp" />
<ClCompileInclude="Sourcecode\FTL\FlashDrv_IF.c" />
<ClCompileInclude="Sourcecode\PTL\UsbDriver.c" />
<ClCompileInclude="stdafx.cpp">
<PrecompiledHeaderCondition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderCondition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompileInclude="U3_MLC.cpp" />
</ItemGroup>
通过上面文件的顺序,我们可以看出,这个顺序是由文件夹及文件名按字段排序得到的。
CSI.c文件依据规则排在最前,那么链接的顺序也是最新的。因为是.c文件,必须是以C编译器来编程,必定是链接标准C库,也即LIBCMTD.lib.
如果我们手动将上面的工程信息调整如下:
<ItemGroup>
<ClCompileInclude="Log.cpp" />
<ClCompile Include="CSI.c"/>
<ClCompileInclude="Sourcecode\FTL\FlashDrv_IF.c" />
<ClCompileInclude="Sourcecode\PTL\UsbDriver.c" />
<ClCompileInclude="stdafx.cpp">
<PrecompiledHeaderCondition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderCondition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompileInclude="U3_MLC.cpp" />
</ItemGroup>
我们再来看工程的搜索链接顺序:
Searching libraries
Searching C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\lib\nafxcwd.lib:
Searching C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\lib\LIBCMTD.lib:
Searching C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\lib\OLDNAMES.lib:
Searching C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.0A\lib\kernel32.lib:
Searching C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.0A\lib\user32.lib:
Searching C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.0A\lib\gdi32.lib:
Searching C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.0A\lib\msimg32.lib:
我们可以看到nafxcwd.lib最先被搜索链接,并且错误也消失了。
由此看来,通过调整.vcproj文件中的文件编译顺序,是可以影响到链接顺序的,是可以解决MFC库和CRT库链接顺序影响的错误的。
但是这种方法有个弊端,即如果下次再添加.c文件或是没有包信预编译头文件的.cpp非MFC类,并且文件名排序在最前,依然可能再次引起上述问题。
微软提供一个针对上述问题的解决方法,建一个Aa.cpp的文件,然后写个如下函数:
因为这个文件名,这个文件自然会被最先链接到,并链接到nafxcwd.lib.即可以解决上述手动调节文件顺序的问题。
算是个取巧的,感觉却怪怪的。
另外,网上还有人提供这样的方法:
Properties->Liker->Command Line->Additional Options: /FORCE:MULTIPLE
针对这个设置,MSDN介绍是
Use/FORCE:MULTIPLE to create an output file whether or not LINK finds more thanone definition for a symbol.
A file created withthis option may not run as expected
其实这种方法,相当于强制链接而忽略重复定义。而且上面的英文也说了,文件虽然创建了,但是未必按预期执行。
所以这种方法是不应该被使用的。
很多时候,有库冲突,很快就会想到忽略冲突库。可是在这里却并不行。因为这两个冲突的库是都要使用的。
所有网上有人提出了这种方法,即开始把两个库Nafxcwd.lib;Libcmtd.lib都忽略掉,然后重新附加这两个库Nafxcwd.lib;Libcmtd.lib。
然后通过查看链接顺序,确实能够正确的链接。
但,事实上没必要这么复杂。我们只需要保证Nafxcwd.lib这个库优先链接即可。事实上,额外附加的库都会优先链接的。
即在Properties->Liner->Input->Additional Dependencies后的编辑框中添加Nafxcwd.lib。这样就使得Nafxcwd.lib最先链接了。
参考资料:
https://msdn.microsoft.com/en-us/library/72zdcz6f.aspx?f=255&MSPPError=-2147217396
https://support.microsoft.com/en-us/kb/148652
https://msdn.microsoft.com/zh-cn/library/70abkas3.aspx?f=255&MSPPError=-2147217396
关于MFC库和CRT库冲突的分析的更多相关文章
- 配置自己的OpenGL库,glew、freeglut库编译,库冲突解决(附OpenGL Demo程序)
平台:Windows7,Visual C++ 2010 1. 引言 实验室的一个项目,用到OpenGL进行实时绘制,还用到一些其他的库,一个困扰我很久的问题就是编译时遇到的各种符号未定义,符号重定义之 ...
- VC中引用第三方库,常见的库冲突问题
Q:VC中引用第三方库,常见的库冲突问题 环境:[1]VS2008 [2]WinXP SP3 A1(方法一): [S1]第三方库(Binary形式的)如果同主程序冲突,则下载第三方库的源码[S2]保持 ...
- 锋利的jQuery-1--解决jquery库和其他库的冲突
在jquery中,$(美元符号)就是jquery的别名,也就是说使用$和使用jquery是一样的,在很多时候我们命名空间时,正是因为这 个$而产生的冲突的发生.比如说:$('#xmlas')和JQue ...
- Jquery库及其他库之间的$命名冲突解决办法
首先我们应该知道,在jquery中,$(美元符号)就是jquery的别名,也就是说使用$和使用jquery是一样的,在很多时候我们命名空间时,正是因为这个$而产生的冲突的发生.比如说:$('#xmla ...
- VC学习笔记---ATL MFC CLR三个库的区别
MFC.ATL和CLR是VC2005内置的三大库,涵盖了Windows的各种开发方法和开发应用.当然关于C++开发的库不止这三个,不过这三个是微软推荐. 从编程所处层次而言,WIN32为最底层,其次是 ...
- jquery库与其他库冲突的问题解决-jquery.noConflict()
在使用jQuery开发的时候,可能还会使用到其他的JS库,比如Prototype,但多库共存时可能会发生冲突:若是发生冲突后,可以通过以下几种方案进行解决: 一. jQuery库在其他库之前导入,直接 ...
- MFC的使用——在共享DLL中使用MFC、在静态库中使用MFC(转)
原文转自 https://blog.csdn.net/albertsh/article/details/52838419 1.使用标准Windows库 使用WINDOWS SDK API库,不使用MF ...
- jquery库与其他库(比如prototype)冲突的解决方法
前端开发很容易会遇到jQuery库与其他库冲突的场景,比如和prototype库冲突. 实际上这种冲突是因为不同的第三方JS库争夺对$标识符的控制权引起的. 解决方法,就是使用jQuery提供的jQu ...
- android.support.design库的引用和冲突解决
android.support.design库的引用和冲突解决 转 https://www.jianshu.com/p/2a0a2af9f2b4 最近在工程中使用到android.support.de ...
随机推荐
- 随手记录一个 firefox的backgroundPostion-x和-y的问题
今天帮大师写了一天项目,后来在测试一个显示升序和降序的标签上面,我使用了一个backgroundPosition-y来判断当前icon的状态,却无法不管是使用闭包还是个钟手段,在 firefox下面总 ...
- linux 下查找大于100M的文件
命令行如下 find . -type f -size +100M Linux系统下查找大文件或目录的技巧 当硬盘空间不够时,我们就很关心哪些目录或文件比较大,看看能否干掉一些了,怎么才能知道呢?以易读 ...
- HTML5-企业宣传6款免费源码
本文主要分享了6个很不错的HTML5宣传模板源码,这些生动具体的介绍了各个公司的产品及公司各类应用,有汽车.旅游.公司,房产等Query特效,大家一起来欣赏吧. 一.九秒教育企业海报(移动端)这次要分 ...
- UVaLive 6602 Counting Lattice Squares (找规律)
题意:给定一个n*m的矩阵,问你里面有几面积为奇数的正方形. 析:首先能知道的是,大的矩阵是包括小的矩阵的,而且面积为奇数,我们只要考虑恰好在边界上的正方形即可,画几个看看就知道了,如果是3*3的有3 ...
- shutdown 和closesocket
来,咱们彻底的来讨论一下这个shutdown 和closesocket 从 函数调用上来分析(msdn):一旦完成了套接字的连接,应当将套接字关闭,并且释放其套接字句柄所占用的所有资源.真正释放一 ...
- hdoj 5349 MZL's simple problem
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5349 #include<stdio.h> int main(){ int cnt; int ...
- hdoj 5327 Olmpiad
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5327 #include<stdio.h> #include<cstring> ...
- 递归模式学习(recursion)
所谓递归,就是方法调用自身.对于递归模式来说,要有一个出口来让递归结束,避免出现死循环. 实例全排列: 从n中拿出m个元素进行排列,当n==m时为全排列. 利用递归就是:把n个元素轮流放入第一个位置, ...
- 跟SAP系统集成的Android应用
首先吐槽一点,这是我的第一个Android应用,很糙. 这个应用适合于上了SAP系统的企业内部使用,并且限于制造型MTO模式,需要针对生产订单报工操作的场景,因为此应用主要的一个目的,就是用来方便报工 ...
- HTML要点(四)<meta>标签
浏览器支持 所有浏览器都支持 <meta> 标签. 定义和用法 <meta> 元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和 ...