LNK2005 LNK1169 Error and LNK4098 Warning

来源:互联网 发布:stm8l编程手册 编辑:程序博客网 时间:2024/05/16 10:40

 

LNK2005 LNK1169 Error and LNK4098 Warning

 

作者:童磊(magictong)

 

静态库冲突的根源

         YY一下链接器的工作方式

此处省略800字……

 

指定链接时的运行时库:

 

 

各编译选项对应的库情况:

编译选项

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 (msvcrt.lib)

libc.lib, libcmt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib

Debug Single-threaded (libcd.lib)

libc.lib, libcmt.lib, msvcrt.lib, libcmtd.lib, msvcrtd.lib

Debug Multithreaded (libcmtd.lib)

libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, msvcrtd.lib

Debug Multithreaded using DLL (msvcrtd.lib)

libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib