现在的位置: 首页 > 综合 > 正文

VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结

2019年03月18日 ⁄ 综合 ⁄ 共 16035字 ⁄ 字号 评论关闭

Background


MSDN中对于在不同的配置下Link的LIB作了说明:
C Runtime
Library

开关
对应的库
版本
/MD
MSVCRT.LIB
多线程DLL的Release版本
/MDd
MSVCRTD.LIB
多线程DLL的Debug版本
/MT
LIBCMT.LIB
多线程静态链接的Release版本
/MTd
LIBCMTD.LIB
多线程静态链接的Debug版本
/clr
MSVCMRT.LIB
托管代码和非托管代码混合
/clr:pure
MSVCURT.LIB
纯托管代码
 
C++ Standard
Library

开关
对应的库
版本
/MD
MSVCPRT.LIB
多线程DLL的Release版本
/MDd
MSVCPRTD.LIB
多线程DLL的Debug版本
/MT
LIBCPMT.LIB
多线程静态链接的Release版本
/MTd
LIBCPMTD.LIB
多线程静态链接的Debug版本
 
编译器会自动根据编译选项,选择对应的LIB文件。一般情况下这不会出现问题。
然而,在部分情况下,一旦你的程序的各个部分(LIB,
OBJ…)并非由相同的编译选项编译出,而Link在一起的话,会出现各种各样的看似很难解决的问题,这类问题主要以重复定义的错误形式存在,通常的解决方法也很简单,就是选择同样的编译选项进行编译之后再Link。
Case Study


之前刚下载了ANTLR,在准备编译它的Example的时候发现了下面的Build错误(我自己为这个例子创建了VS的项目,当前配置为动态链接Runtime库,Debug版):
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char>
>::~basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >(void)"
(??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already
defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > &
__thiscall std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::replace(unsigned int,unsigned int,char const
*,unsigned int)"
(?replace@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@IIPBDI@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: void __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char>
>::reserve(unsigned int)"
(?reserve@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEXI@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: unsigned int __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char>
>::length(void)const "
(?length@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > &
__thiscall std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::operator+=(class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > const &)"
(??Y?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV01@ABV01@@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char>
>::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > const &)"
(??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@ABV01@@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: char const & __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char>
>::operator[](unsigned int)const "
(??A?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEABDI@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > &
__thiscall std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::operator=(class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > const &)"
(??4?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV01@ABV01@@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > &
__thiscall std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::operator=(char const *)"
(??4?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV01@PBD@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char>
>::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >(char const *)"
(??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > __cdecl
std::operator+<char,struct std::char_traits<char>,class
std::allocator<char> >(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > const
&,class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > const &)"
(??$?HDU?$char_traits@D@std@@V?$allocator@D@1@@std@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@ABV10@0@Z)
already defined in antlr.lib(MismatchedCharException.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: char const * __thiscall std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char>
>::c_str(void)const "
(?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "bool __cdecl std::operator<<char,struct
std::char_traits<char>,class std::allocator<char> >(class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > const &,class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > const &)"
(??$?MDU?$char_traits@D@std@@V?$allocator@D@1@@std@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@0@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_ostream<char,struct
std::char_traits<char> > & __thiscall
std::basic_ostream<char,struct std::char_traits<char>
>::operator<<(class std::basic_ostream<char,struct
std::char_traits<char> > & (__cdecl*)(class
std::basic_ostream<char,struct std::char_traits<char> > &))"
(??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_ostream<char,struct
std::char_traits<char> > & __thiscall
std::basic_ostream<char,struct std::char_traits<char>
>::operator<<(int)"
(??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z) already defined
in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "class std::basic_ostream<char,struct std::char_traits<char>
> & __cdecl std::endl(class std::basic_ostream<char,struct
std::char_traits<char> > &)"
(?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z) already
defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: void __thiscall std::basic_ios<char,struct
std::char_traits<char> >::setstate(int,bool)"
(?setstate@?$basic_ios@DU?$char_traits@D@std@@@std@@QAEXH_N@Z) already defined
in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: int __thiscall std::ios_base::width(int)"
(?width@ios_base@std@@QAEHH@Z) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: int __thiscall std::basic_streambuf<char,struct
std::char_traits<char> >::sputn(char const *,int)"
(?sputn@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QAEHPBDH@Z) already
defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: static bool __cdecl
std::char_traits<char>::eq_int_type(int const &,int const &)"
(?eq_int_type@?$char_traits@D@std@@SA_NABH0@Z) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: static int __cdecl std::char_traits<char>::eof(void)"
(?eof@?$char_traits@D@std@@SAHXZ) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: int __thiscall std::basic_streambuf<char,struct
std::char_traits<char> >::sputc(char)"
(?sputc@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QAEHD@Z) already defined
in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_streambuf<char,struct
std::char_traits<char> > * __thiscall std::basic_ios<char,struct
std::char_traits<char> >::rdbuf(void)const "
(?rdbuf@?$basic_ios@DU?$char_traits@D@std@@@std@@QBEPAV?$basic_streambuf@DU?$char_traits@D@std@@@2@XZ)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: char __thiscall std::basic_ios<char,struct
std::char_traits<char> >::fill(void)const "
(?fill@?$basic_ios@DU?$char_traits@D@std@@@std@@QBEDXZ) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: int __thiscall std::ios_base::flags(void)const "
(?flags@ios_base@std@@QBEHXZ) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: int __thiscall std::ios_base::width(void)const "
(?width@ios_base@std@@QBEHXZ) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: static unsigned int __cdecl
std::char_traits<char>::length(char const *)"
(?length@?$char_traits@D@std@@SAIPBD@Z) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_ostream<char,struct
std::char_traits<char> > & __thiscall
std::basic_ostream<char,struct std::char_traits<char>
>::flush(void)"
(?flush@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV12@XZ) already
defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: class std::basic_ostream<char,struct
std::char_traits<char> > * __thiscall std::basic_ios<char,struct
std::char_traits<char> >::tie(void)const "
(?tie@?$basic_ios@DU?$char_traits@D@std@@@std@@QBEPAV?$basic_ostream@DU?$char_traits@D@std@@@2@XZ)
already defined in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: bool __thiscall std::ios_base::good(void)const "
(?good@ios_base@std@@QBE_NXZ) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: void __thiscall std::basic_ostream<char,struct
std::char_traits<char> >::_Osfx(void)"
(?_Osfx@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEXXZ) already defined in
antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: void __thiscall std::basic_streambuf<char,struct
std::char_traits<char> >::_Lock(void)"
(?_Lock@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QAEXXZ) already defined
in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "public: void __thiscall std::basic_streambuf<char,struct
std::char_traits<char> >::_Unlock(void)"
(?_Unlock@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QAEXXZ) already defined
in antlr.lib(CharScanner.obj)
1>msvcprtd.lib(MSVCP80D.dll) : error
LNK2005: "class std::basic_ostream<char,struct std::char_traits<char>
> & __cdecl std::operator<<<char,struct
std::char_traits<char>,class std::allocator<char> >(class
std::basic_ostream<char,struct std::char_traits<char> > &,class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > const &)"
(??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z)
already defined in antlr.lib(LLkParser.obj)
1>libcpmt.lib(locale0.obj) : error LNK2005:
"private: static class std::locale::_Locimp * __cdecl
std::locale::_Getgloballocale(void)"
(?_Getgloballocale@locale@std@@CAPAV_Locimp@12@XZ) already defined in
msvcprtd.lib(MSVCP80D.dll)
1>libcpmt.lib(locale0.obj) : error LNK2005:
"private: static void __cdecl std::locale::facet::facet_Register(class
std::locale::facet *)" (?facet_Register@facet@locale@std@@CAXPAV123@@Z) already
defined in msvcprtd.lib(MSVCP80D.dll)
1>libcpmt.lib(locale0.obj) : error LNK2005:
"public: static void __cdecl std::_Locinfo::_Locinfo_dtor(class std::_Locinfo
*)" (?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z) already defined in
msvcprtd.lib(MSVCP80D.dll)
1>libcpmt.lib(locale0.obj) : error LNK2005:
"public: static void __cdecl std::_Locinfo::_Locinfo_ctor(class std::_Locinfo
*,char const *)" (?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@PBD@Z) already defined
in msvcprtd.lib(MSVCP80D.dll)
1>libcpmt.lib(xmutex.obj) : error LNK2005:
"public: void __thiscall std::_Mutex::_Lock(void)" (?_Lock@_Mutex@std@@QAEXXZ)
already defined in msvcprtd.lib(MSVCP80D.dll)
1>libcpmt.lib(xmutex.obj) : error LNK2005:
"public: void __thiscall std::_Mutex::_Unlock(void)"
(?_Unlock@_Mutex@std@@QAEXXZ) already defined in
msvcprtd.lib(MSVCP80D.dll)
1>libcpmt.lib(xlock.obj) : error LNK2005:
"public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z)
already defined in msvcprtd.lib(MSVCP80D.dll)
1>libcpmt.lib(xlock.obj) : error LNK2005:
"public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ)
already defined in msvcprtd.lib(MSVCP80D.dll)
1>LIBCMT.lib(invarg.obj) : error LNK2005:
__invoke_watson already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(invarg.obj) : error LNK2005:
__invalid_parameter already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(setlocal.obj) : error LNK2005:
__configthreadlocale already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(tidtable.obj) : error LNK2005:
__encode_pointer already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(tidtable.obj) : error LNK2005:
__decode_pointer already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(tolower.obj) : error LNK2005:
_tolower already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(crt0dat.obj) : error LNK2005:
__amsg_exit already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(crt0dat.obj) : error LNK2005:
__initterm_e already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(crt0dat.obj) : error LNK2005:
_exit already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(crt0dat.obj) : error LNK2005:
__exit already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(crt0dat.obj) : error LNK2005:
__cexit already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(lconv.obj) : error LNK2005:
_localeconv already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(mlock.obj) : error LNK2005:
__unlock already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(mlock.obj) : error LNK2005:
__lock already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(winxfltr.obj) : error LNK2005:
__XcptFilter already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(crt0init.obj) : error LNK2005:
___xi_a already defined in MSVCRTD.lib(cinitexe.obj)
1>LIBCMT.lib(crt0init.obj) : error LNK2005:
___xi_z already defined in MSVCRTD.lib(cinitexe.obj)
1>LIBCMT.lib(crt0init.obj) : error LNK2005:
___xc_a already defined in MSVCRTD.lib(cinitexe.obj)
1>LIBCMT.lib(crt0init.obj) : error LNK2005:
___xc_z already defined in MSVCRTD.lib(cinitexe.obj)
1>LIBCMT.lib(hooks.obj) : error LNK2005:
"void __cdecl terminate(void)" (?terminate@@YAXXZ) already defined in
MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(crt0.obj) : error LNK2005:
_mainCRTStartup already defined in MSVCRTD.lib(crtexe.obj)
1>LIBCMT.lib(errmode.obj) : error LNK2005:
___set_app_type already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMT.lib(_ctype.obj) : error LNK2005:
_isprint already defined in MSVCRTD.lib(MSVCR80D.dll)
1>MSVCRTD.lib(MSVCR80D.dll) : error LNK2005:
__stricmp already defined in LIBCMT.lib(stricmp.obj)
1>LINK : warning LNK4098: defaultlib
'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
1>LINK : warning LNK4098: defaultlib
'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library
1>D:/home/doc/Visual Studio
2005/Projects/tst_antlr_3/Debug/tst_antlr_3.exe : fatal error LNK1169: one or
more multiply defined symbols found
分析一下错误来源,会发现:
1.    
错误来源主要是重复定义的问题,而且重复定义的基本上都是VC
Runtime和Standard C++ Library中的函数
2.    

LIBCMT和LIBCPMT为Release下的Lib,本来不应该出现在Debug版本的链接的Lib中
3.    
重复定义的问题主要出现在:LIBCMT, LIBCPMT,
MSVCPRTD, MSVCRTD
来看看出问题的LIB是那些:
1.    
LIBCMT:C
Runtime库的多线程静态链接的Release版本
2.    
LIBCPMT:C++ Standard
Library的多线程静态链接的Release版本
3.    
MSVCPRTD:C++ Standard
Library的多线程DLL的Debug版本
4.    
MSVCRTD:C Runtime
Library的多线程DLL的Debug版本
当前我们的配置是多线程DLL的Debug版,因此3和4是应该出现在link的列表中的,不属于多余。而后两者则是只是当多线程静态链接Release版中才会出现。这提示我在项目中加入的ANTLR.LIB可能是造成这个问题的根源,因为静态库的编译选项很容易和主程序发生冲突,并且根据实际信息我们可以看出ANTLR.LIB应该是用多线程静态链接的Release版本来编译的。
这样,解决方法就很清楚了:
1.    

切换到Release,因为ANTLR.LIB是在Release下面编译的
2.    
把Run Time库的版本修改成多线程静态链接
做了这两个修改之后编译通过。
还有一种方法是,自己用多线程DLL的Debug版重新编译一次ANTLR,生成一个新的ANTLRD.LIB,再link这个Lib也可以解决这个问题。
Summary

1.    

知道各个不同的LIB代表的版本信息非常重要,可以帮助快速定位问题
2.    

在编程的时候,一定要把所有的项目的编译选项(是静态链接Runtime库还是动态链接Runtime库,Debug/Release)配置成一样的。如果部分LIB/OBJ是由第三方提供(OBJ情况很少见),一般情况下只能调整自己的编译选项,除非你可以要求第三方提供其他版本的编译好的LIB
3.    

在发布可重用的静态LIB库供其他人调用的时候,最好对应不同的编译选项,乃至VC版本,提供不同版本的LIB。VC自己的Runtime就是最好的例子。

抱歉!评论已关闭.