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(void)” (??1?

basictring@DU?

s

char_traits@D@std@@V?KaTeX parse error: Expected 'EOF', got '&' at position 218: …ocator > & __thiscall

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::operator+=(class

std::basic_string const &)” (??Y?

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 > & __thiscall std…basic_string@DU?

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::operator=(char const *)” (??4?

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+(class std::basic_string

std::char_traits,class std::allocator > const &,class std::basic_string const

&)” (??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 > & __thiscall std…basic_ostream@DU?KaTeX parse error: Expected 'EOF', got '&' at position

219: …traits > & __thiscall std…basic_ostream@DU?KaTeX parse error: Expected 'EOF', got '&' at position 195: …

traits > & __cdecl std::e…basic_ostream@DU?KaTeX parse error: Expected group after '_' at position 139: … "public:

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 > * __thiscall std::…basic_ios@DU?

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 & __thiscall

std::basic_ostream::flush(void)” (?flush@?

basicstream@DU?

o

char_traits@D@std@@@std@@QAEAAV12@XZ) already defined in ()

1>() : error LNK2005: "public: class std::basic_ostream * __thiscall

std::basic_ios::tie(void)const " (?tie@?char_traits@D@std@@@std@@QBEPAV?

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 & __cdecl

std::operator<<(class std::basic_ostream

&,class std::basic_string const &)” (??char_traits@D@std@@V?

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 ()

分析⼀下错误来源,会发现: