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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结相关的知识,希望对你有一定的参考价值。

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)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]) 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)" ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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)" ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]) 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 " ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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 &)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@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 &)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@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 " ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]) 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 &)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@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 *)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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 *)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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 &)" ([email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]) 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 " ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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 &)" ([email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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> > &))" ([email protected][email protected]@[email protected]@@[email protected]@[email protected]@[email protected]@[email protected]) 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)" ([email protected][email protected]@[email protected]@@[email protected]@[email protected]@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> > &)" ([email protected]@@[email protected][email protected]@[email protected]@@[email protected]@@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)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected]) already defined in antlr.lib(CharScanner.obj)

1>msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: int __thiscall std::ios_base::width(int)" ([email protected][email protected]@@[email protected]) 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)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected]) 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 &)" ([email protected][email protected]@[email protected]@[email protected]) already defined in antlr.lib(CharScanner.obj)

1>msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: static int __cdecl std::char_traits<char>::eof(void)" ([email protected][email protected]@[email protected]@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)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected]) 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 " ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@@[email protected]) 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 " ([email protected][email protected][email protected]@[email protected]@@[email protected]@QBEDXZ) already defined in antlr.lib(CharScanner.obj)

1>msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: int __thiscall std::ios_base::flags(void)const " ([email protected][email protected]@@QBEHXZ) already defined in antlr.lib(CharScanner.obj)

1>msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: int __thiscall std::ios_base::width(void)const " ([email protected][email protected]@@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 *)" ([email protected][email protected]@[email protected]@[email protected]) 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)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected]) 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 " ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@@[email protected]) already defined in antlr.lib(CharScanner.obj)

1>msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: bool __thiscall std::ios_base::good(void)const " ([email protected][email protected]@@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)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@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)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@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)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@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 &)" ([email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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)" ([email protected]@[email protected]@[email protected]@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 *)" ([email protected]@[email protected]@@[email protected]@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 *)" ([email protected][email protected]@@[email protected]@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 *)" ([email protected][email protected]@@[email protected]@Z) already defined in msvcprtd.lib(MSVCP80D.dll)

1>libcpmt.lib(xmutex.obj) : error LNK2005: "public: void __thiscall std::_Mutex::_Lock(void)" ([email protected][email protected]@@QAEXXZ) already defined in msvcprtd.lib(MSVCP80D.dll)

1>libcpmt.lib(xmutex.obj) : error LNK2005: "public: void __thiscall std::_Mutex::_Unlock(void)" ([email protected][email protected]@@QAEXXZ) already defined in msvcprtd.lib(MSVCP80D.dll)

1>libcpmt.lib(xlock.obj) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" ([email protected]@@[email protected]@Z) already defined in msvcprtd.lib(MSVCP80D.dll)

1>libcpmt.lib(xlock.obj) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" ([email protected]@@[email protected]) 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)" ([email protected]@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就是最好的例子。

以上是关于VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结的主要内容,如果未能解决你的问题,请参考以下文章

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

typedef 结构在链接静态库时会导致名称冲突吗?

vc下DLL项目设置dll和lib库输出路径以及使用lib/dll库时的包含路径

我们可以静态链接动态 C 库吗?

链接静态库时链接器可以省略目标文件吗?

Anaconda 将 C/C++ 链接器与重复库混淆