指定链接时的运行时库:
各编译选项对应的库情况:
编译选项 | CRT | CPPRT | 说明 |
/ML | libc.lib |
| 单线程库 |
/MLd | libcd.lib |
| 单线程调试库 |
/MT | libcmt.lib | libcpmt.lib | 多线程静态库 |
/MTd | libcmtd.lib | libcpmtd.lib | 多线程静态调试库 |
/MD | msvcrt.lib(msvcrt.dll) | msvcprt.lib(msvcprt.dll) | 多线程动态库 |
/MDd | msvcrtd.lib(msvcrtd.dll) | msvcprtd.lib(msvcprtd.dll) | 多线程动态调试库 |
一般来说编译器会根据编译选项自动选择对应的标准库。
例子说明(暴露问题)
---------------------------------------------------------------------------------------------------------------------------------
情景一:
app: MT
lib: MD
LIBCMT.lib(crt0init.obj) : warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
因为你显式指定的标准库版本与目标文件的缺省值不一致。通常来说,应该保证链接器合并的所有目标文件指定的缺省标准库版本一致,否则编译器一定会给出上面的警告
情景二:
app: MD
lib: MT
MSVCRT.lib(cinitexe.obj) : warning LNK4098: defaultlib 'libcmt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
情景三:
app: MD
lib: MDd
MSVCRT.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrtd.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
情景四:
app: MT
lib: MTd
lib中使用了
#include <crtdbg.h>
_malloc_dbg(1, _NORMAL_BLOCK, __FILE__, __LINE__);
1>Linking...
1>libcmtd.lib(dbgheap.obj) : error LNK2005: _malloc already defined in LIBCMT.lib(malloc.obj)
1>libcmtd.lib(dbgheap.obj) : error LNK2005: __heap_alloc already defined in LIBCMT.lib(malloc.obj)
1>libcmtd.lib(dbgheap.obj) : error LNK2005: _calloc already defined in LIBCMT.lib(calloc.obj)
1>libcmtd.lib(dbgheap.obj) : error LNK2005: _realloc already defined in LIBCMT.lib(realloc.obj)
1>libcmtd.lib(dbgheap.obj) : error LNK2005: __recalloc already defined in LIBCMT.lib(realloc.obj)
1>libcmtd.lib(dbgheap.obj) : error LNK2005: _free already defined in LIBCMT.lib(free.obj)
1>libcmtd.lib(dbgheap.obj) : error LNK2005: __msize already defined in LIBCMT.lib(msize.obj)
1>libcmtd.lib(malloc.obj) : error LNK2005: _V6_HeapAlloc already defined in LIBCMT.lib(malloc.obj)
1>libcmtd.lib(dbghook.obj) : error LNK2005: __crt_debugger_hook already defined in LIBCMT.lib(dbghook.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_pHeaderDefer already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: __set_sbh_threshold already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: __set_amblksiz already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: __get_amblksiz already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_heap_init already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_find_block already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_free_block already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_alloc_block already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_alloc_new_region already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_alloc_new_group already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_resize_block already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_heapmin already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(sbheap.obj) : error LNK2005: ___sbh_heap_check already defined in LIBCMT.lib(sbheap.obj)
1>libcmtd.lib(isctype.obj) : error LNK2005: __isctype_l already defined in LIBCMT.lib(isctype.obj)
1>libcmtd.lib(isctype.obj) : error LNK2005: __isctype already defined in LIBCMT.lib(isctype.obj)
1>LIBCMT.lib(crt0init.obj) : warning LNK4098: defaultlib 'libcmtd.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
1>H:\prj\CRTSetting\LibLoader\Release\LibLoader.exe : fatal error LNK1169: one or more multiply defined symbols found
解决方案:
· 我们在编程的时候,一定要把所有的工程的编译选项配置成一样的(主要是静态库和引用静态库的工程的,debug对应debug,release对应release的,一一对应)。
· 如果部分LIB是由第三方提供的怎么办?,譬如我们引用了zlib的静态库(一般第三方发布的静态库都有多个版本),这种情况下一般只能调整自己的编译选项,或者可能使用Ignore Specific Library 编译选项能解决问题,但是根据上面做的实验我们知道这种方法不能解决所有问题(关于Ignore Specific Library的用法可以参见链接:http://blog.csdn.net/magictong/archive/2010/12/29/6105160.aspx)。
· 如果我们发布静态LIB库给别人使用,最好对应不同的编译选项,甚至不同的vs版本,提供不同版本的LIB。
Ignore Specific Library Table
使用下面的运行时库 | 需要忽略的库 |
Single-threaded (libc.lib) | libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib |
Multithreaded (libcmt.lib) | libc.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib |
Multithreaded using DLL |
注:当你检查完当前的应用程序和所有链接的dll或者lib,他们的crt配置都一样的时候,仍然有link2005错误时候,可以清除当前工程,再编译链接,可能link2005错误就消失了,这种情况尤其在”批生成“菜单命令项时,表现尤为突出。