2023年11月29日发(作者:)
C++⼯程编译之“errorLNK2001:⽆法解析的外部符号”
本⽂全部转⾃博客园⽤户VictoKu 原⽂链接:
今天⼀整天都在折腾“error LNK2001: ⽆法解析的外部符号”,就在头疼不已的时候,总算是找到问题原因了:各个动态链接库的编译⽅
式必须统⼀才⾏,要不然很容易对库函数的引⽤产⽣冲突。简单来说就是,如果使⽤的第三⽅函数库编译⽅式采⽤/MD,那么主⼯程也应该
使⽤/MD。我使⽤了libevent,⽽主⼯程默认采⽤/MT,所以需要忽略⼀⼤堆的函数库,我还纳闷呢,怎么会这么奇怪!!今天总算是解决
了长久以来的困惑了。
下⾯引⽤⼀篇⽂章的描述:[Z]VC运⾏库版本不同导致链接.LIB静态库时发⽣重复定义问题的⼀个案例分析和总结
再参考⼀篇:() : error LNK2005:已经在() 中定义
1. 多个dll被⼀个exe LoadLibrary加载,如果这些dll使⽤的运⾏时库是不同的,那么可能出现加载失败,原因可能是旧版本的运⾏时库
已经在了,⽽某个dll它需要的是新版本的运⾏时库,旧版本不符合要求。
2. 如果⼯程⾥所有的模块都是⾃⼰写的或者可以完全控制的,那么这个问题不难解决,只需要在⼯程设置⾥都设置/MD,然后在相同的
环境下编译⼀次就⾏。但是假如这个模块是外界提供的呢?
3. 可能存在这种情况:A动态库使⽤了B静态库,B静态库使⽤了C动态库,B静态库是外界提供的,我们要使⽤它,但⽆法修改它,我们
也⽆法接触到C动态库。如果C动态库使⽤的运⾏时库版本跟编译A动态库的本地使⽤的不⼀致,那么A动态库⾥的嵌⼊信息就会记录
两个不同版本的运⾏时库,它被加载的时候,可能会选择版本新的。假设A动态库被⼀个exe LoadLibrary加载,⽽这个exe本⾝的运
⾏时库是旧的,这样就会导致A动态库加载失败,即便把新的运⾏时库拷贝到⽬录下也不⾏,因为exe这个进程已经加载了那个旧的运
⾏时库。这时候必须使⽤manifest⽂件指定嵌⼊到A动态库⾥的运⾏时库为某个版本,忽略掉C动态库使⽤的运⾏时库版本。
4. 这个问题挺复杂的,我⼼思没去验证windows的PE⽂件加载会对运⾏时库做什么样的优先选择、运⾏时库在静态库⾥的记录…。只要
记住,给外界使⽤的组件版本尽量避免使⽤/MD(这样会导致膨胀吗?据说,安装包可以做字节流式压缩)。
5. 附上另⼀个问题:静态库的依赖关系:exe–>libA–>libB,现在不想让exe接触到libB,于是把libA的librarian选项–>General选
项–>Link Library Dependencies设置为Yes,这样即可,libA会包含libB,exe只需要接触libA。另外需要特别注意,libA对libB的
依赖只需要且只能在Solution的Project Dependencies⾥设置,如果在libA的代码⾥写了”#pragma comment(lib,
“”)”,会导致exe在link libA的时候提⽰找不到libA。如果exe还出现link错误,那⼀定是VS抽筋了:)
2、为什么选择/MT,不选择/MD?
(1)有些系统可能没有程序所需要版本的运⾏时库,程序必须把运⾏时库静态链接上。
(2)减少模块对外界的依赖。
选择/MT 时存在⼀个“堆空间释放”的问题:
1. 不同的模块各⾃有⼀份C运⾏时库代码、或者根本没有C运⾏时库,导致了各个模块会有各⾃的堆。如果在A堆中申请空间,到B堆中
释放就会有崩溃,在模块A申请的空间,必须在模块A中释放。
3、多个模块,必须选择相同的运⾏时库。
Case Study
之前刚下载了ANTLR,在准备编译它的Example的时候发现了下⾯的Build错误(我⾃⼰为这个例⼦创建了VS的项⽬,当前配置为动
态链接Runtime库,Debug版):
1>() : error LNK2005: “public: __thiscall std::basic_string std::allocator >::~basic_string basictring@DU? s char_traits@D@std@@V?KaTeX parse error: Expected 'EOF', got '&' at position 218: …ocator std…basic_string@DU?allocator@D@2@@std@@QAEAAV12@IIPBDI@Z) already defined in charraits@D@std@@V? t () 1>() : error LNK2005: “public: void __thiscall std::basic_string std::allocator >::reserve(unsigned int)” (?reserve@?char_traits@D@std@@V?KaTeX parse error: Expected basictring@DU? s group after '_' at position 144: …: unsigned int __thiscall std::…basic_string@DU? charraits@D@std@@V? t allocator@D@2@@std@@QBEIXZ) already defined in () 1>() : error LNK2005: “public: class std::basic_string std::allocator > & __thiscall std::basic_string std::basic_string basictring@DU? s char_traits@D@std@@V?KaTeX parse error: Expected group after '_' at position 141: …2005: "public: __thiscall std:: …basic_string@DU?allocator@D@2@@std@@QAE@ABV01@@Z) already defined in charraits@D@std@@V? t () 1>() : error LNK2005: "public: char const & __thiscall std::basic_string std::char_traits,class std::allocator >::operator[](unsigned int)const " (??A?char_traits@D@std@@V?KaTeX basictring@DU? s parse error: Expected 'EOF', got '&' at position 221: …ocator charraits@D@std@@V? t allocator@D@2@@std@@QAEAAV01@ABV01@@Z) already defined in () 1>() : error LNK2005: “public: class std::basic_string std::allocator > & __thiscall std::basic_string basictring@DU? s char_traits@D@std@@V?KaTeX parse error: Expected group after '_' at position 138: …2005: "public: basictring@DU? s char_traits@D@std@@V?KaTeX parse error: Expected group after '_' at position 138: …2005: "public: __thiscall std::…basic_string@DU?allocator@D@2@@std@@QAE@PBD@Z) already defined in charraits@D@std@@V? t () 1>() : error LNK2005: “class std::basic_string __cdecl std::operator+ std::char_traits,class std::allocator > const &,class std::basic_string &)” (??char_traits@D@std@@V?basic_string@DU? HDU?allocator@D@1@@std@@YA?AV?charraits@D@std@@V? t allocator@D@2@@0@ABV10@0@Z) already defined in () 1>() : error LNK2005: "public: char const * __thiscall std::basic_string std::char_traits,class std::allocator >::c_str(void)const " (?c_str@?char_traits@D@std@@V?KaTeX parse basictring@DU? s error: Expected group after '_' at position 129: …LNK2005: "bool __cdecl std::ope…?MDU? charraits@D@std@@V? t allocator@D@1@@std@@YA_NABV?char_traits@D@std@@V?KaTeX parse error: Expected 'EOF', got '&' basictring@DU? s at position 186: …traits 219: …traits traits void __thiscall std::…basic_ios@DU?KaTeX parse error: Expected group after '_' at position 142: …: "public: int __thiscall std:: …basic_streambuf@DU?KaTeX parse error: Expected group after '_' at position 151: …c: static bool __cdecl std::cha…char_traits@D@std@@SA_NABH0@Z) already defined in () 1>() : error LNK2005: “public: static int __cdecl std::char_traits::eof(void)” (?eof@?KaTeX parse error: Expected group after '_' at position 132: …: "public: int __thiscall std::…basic_streambuf@DU?KaTeX parse error: Expected group after '_' at position 202: …aits charraits@D@std@@@std@@QBEPAV? t basic_streambuf@DU?KaTeX parse error: Expected group after '_' at position 133: … "public: char __thiscall std::…basic_ios@DU?KaTeX parse error: Expected group after '_' at position 139: …: "public: int __thiscall std::…char_traits@D@std@@SAIPBD@Z) already defined in () 1>() : error LNK2005: “public: class std::basic_ostream std::basic_ostream basicstream@DU? o char_traits@D@std@@@std@@QAEAAV12@XZ) already defined in () 1>() : error LNK2005: "public: class std::basic_ostream std::basic_ios basicos@DU? i basicstream@DU? o char_traits@D@std@@@2@XZ) already defined in () 1>() : error LNK2005: "public: bool __thiscall std::ios_base::good(void)const " (? good@ios_base@std@@QBE_NXZ) already defined in () 1>() : error LNK2005: “public: void __thiscall std::basic_ostream >::_Osfx(void)” (?_Osfx@?char_traits@D@std@@@std@@QAEXXZ) already defined in basicstream@DU? o () 1>() : error LNK2005: “public: void __thiscall std::basic_streambuf >::_Lock(void)” (?_Lock@?char_traits@D@std@@@std@@QAEXXZ) already defined in basictreambuf@DU? s () 1>() : error LNK2005: “public: void __thiscall std::basic_streambuf >::_Unlock(void)” (?_Unlock@?char_traits@D@std@@@std@@QAEXXZ) already defined in basictreambuf@DU? s () 1>() : error LNK2005: “class std::basic_ostream std::operator<< &,class std::basic_string 6DU? allocator@D@1@@std@@YAAAV?charraits@D@std@@@0@AAV10@ABV? basic_ostream@DU?basic_string@DU? t charraits@D@std@@V? t allocator@D@2@@0@@Z) already defined in () 1>() : error LNK2005: “private: static class std::locale::_Locimp * __cdecl std::locale::_Getgloballocale(void)” (?_Getgloballocale@locale@std@@CAPAV_Locimp@12@XZ) already defined in () 1>() : 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 () 1>() : error LNK2005: “public: static void __cdecl std::_Locinfo::_Locinfo_dtor(class std::_Locinfo *)” (?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z) already defined in () 1>() : 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 () const *)” (?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@PBD@Z) already defined in () 分析⼀下错误来源,会发现:


发布评论