[背景回顾]

我们都知道lib静态库只是各个obj打包的一个集合格式,如果链接器在链接时都将参与链接的lib完全解包提取每一个obj效率是比较低的;(注意它与直接参与链接的在主程从cpp编译到的obj不同)

假定f函数所在的obj是独立的(假如它在f.obj中),且还有其他编译单元的a.obj(假如有add函数)引入f,它们均在同一个lib中打包(也就是xxx.lib={f.obj, a.obj}),现在外层主项目现在假定已经有了f()的源文件定义,那么f.obj会不会被提取?

msvc看待lib文件中的obj是否被提取当且仅当一个符号在“主项目层”(指当前已编译的产物中)以及“外层”完全找不到时(关于什么是“外层”放在下面实验中可进一步体会到),才会抽取所有lib文件中的符号做去做绑定(常规情况下只是待定状态),而且在一个lib中找到符号后就不会再去展开挖另一个lib库中的obj去找重复的符号;

那么以上这种情况也就不会链接时造成符号重定义,而且优先绑定的时候是主项目源文件f的那个编译后的obj,

但这种情况反而更加危险,因为你压根不知道两个库所依赖的底层库版本是不是同一个又或者能否相互兼容,当不兼容时这个坑在链接期连报错都不会跟你说,除非函数参数这些签名不一致时导致重载失败那么才会明显报出~

 

[实验开始]——这里我们只做“外层”那种不会链接报重定义错的

(因为主项目层的那种这篇已经做过用户模块版本隔离问题.mht)
外层具体指的是在lib库中obj有依赖另一个库中obj中的符号,若相对它来说的外层(即这里可能是主项目层)已经具有该符号了,那么该所谓另一个库中的obj压根就不会提取出来,并且这可能还跟外层中引入lib的顺序有关。。

实验对象:
1. libcurl(已从官方编译的lib静态库8.11版本,当中依赖zlib的外联静态库为1.3.2)、
2. 我们自己另开项目DIY编译的zlib库(那么现在就已经有两个zlib库了)

curl_native模块就两个lib(其中叫zs.lib的就是curl自带的zlib库),会在模块引入后的生成时自动参与链接

这当中有个函数是zlibVersion(),它在库中调用后返回的结果为1.3.2

 

在我们DIY的zlib源码里随意改一下它的版本号比如(1.3.3),

这样该库中的zlibVersion这个函数调用返回的就是1.3.3,然后我们把自己的该工程编译出BE_zlib.lib

 

接着我们再另开个项目测一下:

(这里BE_zlib.lib写在后,而stdafx.h中是含专属的BEMod,所以有自动引入curl中的zs.lib)

这个编译链接后是能通过,确实也没有报符号重定义的问题!

但如果我们现在换个位置(BE_zlib.lib放在最前——链接器会优先链接它,注意在做该实验时你必须要【清理】或【重新生成】否则它有上次的链接缓存):

额,这里1.3.3了,完全没有报任何链接期的符号重定义!

 

对此,白易有解决方案将在:用户模块版本隔离问题.mht 中彻底被解决!

 


[当然我顺带还额外问了下AI]