当MFC库和CRT库冲突时,会出现一个LNK2005的错误。具体的错误如下:

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的文件,然后写个如下函数:

int test(){new int; return 1;}

因为这个文件名,这个文件自然会被最先链接到,并链接到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库冲突的分析的更多相关文章

  1. 配置自己的OpenGL库,glew、freeglut库编译,库冲突解决(附OpenGL Demo程序)

    平台:Windows7,Visual C++ 2010 1. 引言 实验室的一个项目,用到OpenGL进行实时绘制,还用到一些其他的库,一个困扰我很久的问题就是编译时遇到的各种符号未定义,符号重定义之 ...

  2. VC中引用第三方库,常见的库冲突问题

    Q:VC中引用第三方库,常见的库冲突问题 环境:[1]VS2008 [2]WinXP SP3 A1(方法一): [S1]第三方库(Binary形式的)如果同主程序冲突,则下载第三方库的源码[S2]保持 ...

  3. 锋利的jQuery-1--解决jquery库和其他库的冲突

    在jquery中,$(美元符号)就是jquery的别名,也就是说使用$和使用jquery是一样的,在很多时候我们命名空间时,正是因为这 个$而产生的冲突的发生.比如说:$('#xmlas')和JQue ...

  4. Jquery库及其他库之间的$命名冲突解决办法

    首先我们应该知道,在jquery中,$(美元符号)就是jquery的别名,也就是说使用$和使用jquery是一样的,在很多时候我们命名空间时,正是因为这个$而产生的冲突的发生.比如说:$('#xmla ...

  5. VC学习笔记---ATL MFC CLR三个库的区别

    MFC.ATL和CLR是VC2005内置的三大库,涵盖了Windows的各种开发方法和开发应用.当然关于C++开发的库不止这三个,不过这三个是微软推荐. 从编程所处层次而言,WIN32为最底层,其次是 ...

  6. jquery库与其他库冲突的问题解决-jquery.noConflict()

    在使用jQuery开发的时候,可能还会使用到其他的JS库,比如Prototype,但多库共存时可能会发生冲突:若是发生冲突后,可以通过以下几种方案进行解决: 一. jQuery库在其他库之前导入,直接 ...

  7. MFC的使用——在共享DLL中使用MFC、在静态库中使用MFC(转)

    原文转自 https://blog.csdn.net/albertsh/article/details/52838419 1.使用标准Windows库 使用WINDOWS SDK API库,不使用MF ...

  8. jquery库与其他库(比如prototype)冲突的解决方法

    前端开发很容易会遇到jQuery库与其他库冲突的场景,比如和prototype库冲突. 实际上这种冲突是因为不同的第三方JS库争夺对$标识符的控制权引起的. 解决方法,就是使用jQuery提供的jQu ...

  9. android.support.design库的引用和冲突解决

    android.support.design库的引用和冲突解决 转 https://www.jianshu.com/p/2a0a2af9f2b4 最近在工程中使用到android.support.de ...

随机推荐

  1. 非对称认证方式 可以用在 asp.net webapi 的安全机制里面

    //Client端调用 static void Main(string[] args) { string publicKey = "DpLMCOihcYI2i6DaMbso9Dzo1miy7 ...

  2. Python程序的混淆和加密

    混淆 为了增加代码阅读的难度, 源代码的混淆非常必要, 一个在线的Python代码混淆网站. 如果你觉得有用, 可以购买离线版本.同时需要注意的是, 这个混淆其实还是被很多人怀疑的, 因为即使混淆了, ...

  3. C++11多态函数对象包装器

    [C++11多态函数对象包装器] 针对函数对象的多态包装器(又称多态函数对象包装器)在语义和语法上和函数指针相似,但不像函数指针那么狭隘.只要能被调用,且其参数能与包装器兼容的都能以多态函数对象包装器 ...

  4. Struts2数据校验方法

    方法: 1.在Action类中execute()方法中进行校验. 优点:Action类无需继承框架中的类. 缺点:(1)当有多个校验时,代码重复,违反高内聚,低耦合. 2.重写框架ActionSupp ...

  5. *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL

    kei编译时提示: *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL *** WARNING L1:reference made to unresolved ext ...

  6. LightOJ 1259 Goldbach`s Conjecture (哥德巴赫猜想 + 素数筛选法)

    http://lightoj.com/volume_showproblem.php?problem=1259 题目大意:给你一个数n,这个数能分成两个素数a.b,n = a + b且a<=b,问 ...

  7. 帮你选处理器:CPU T9500-p9500-T9400-T9300-p8700对比分析!

    许多人对处理器是P和T开头含混不清,不甚了解,也怪英特尔的处理器型号实在是太过复杂.这需要具体型号来看的.让我们先来看看英特尔的官方解释吧 T: Mobile Highly Performance-- ...

  8. jshint 安装使用

    首先要安装nodjs, 参考另一篇文章: Ubuntu 编译安装node.js 然后运行 npm install jshint -g 之后在要扫描的目录下运行命令 jshint . >> ...

  9. F5 会话保持

    1.什么是会话保持?在大多数电子商务的应用系统或者需要进行用户身份认证的在线系统中,一个客户与服务器经常经过好几次的交互过程才能完成一笔交易或者是一个请求的完成.由于这几次交互过程是密切相关的,服务器 ...

  10. 【CSDN博客之星】2013年CSDN博客之星正在评选,希望大家支持,非常感谢!

    首先在此感谢 MoreWindows 秒杀多线程面试题系列让我成长和学习,同时也借鉴了很多优秀观点和示例! 请各位读者可以支持MoreWindows,让更优秀的文章陪伴我们! 各位读者好, 本人博客自 ...