如何嵌入静态库的副本?

时间:2020-01-17 12:51:21

标签: c++ visual-c++ visual-studio-2017 linker

这是我的解决方案的结构:

enter image description here

A.lib定义:

int a(void) { return 1; }

B.lib定义:

int b(void) { return a(); }

C.lib定义:

int c(void) { return a() * 2; }

SharedStaticLibsTest.exe定义:

int main(void) { std::cout << b() + c() << std::endl; return 0;}

我决定(通过DumpBin)检查嵌入到结果应用程序中的代码。事实证明,BC库使用A库的唯一实例。有什么方法(出于教育目的)在AB中使用C的两个不同实例?也许对于这个东西有链接器的特定选择?我了解,这种行为可能会产生意想不到的副作用,这取决于A库的逻辑。

P.S。我通过在项目属性中直接包含.lib文件来替换对项目的引用。现在BC个项目有一个A项目的副本。但是最终项目仍具有A库的唯一副本。我不知道链接程序如何解决这个问题。

1 个答案:

答案 0 :(得分:4)

首先,如果最终在构建中遇到两个A实例,则从A导出的所有标识符都必须遵循One-Definition-Rule

也就是说,即使您在技术上可以拥有A的两个不同版本,除非它们在所有意图和目的上都是相同的,否则您的程序是无效的,并且编译器和链接器都没有义务告诉您( C ++标准将其称为格式错误,无需诊断)。实际上,这意味着您的程序中将有很多个怪异的bug,并且不知道它们来自何处。

话虽如此,从技术上讲,没有什么可以阻止您构造类似您所要求的情况。通常,静态依赖项仅在链接阶段进行处理。因此,依赖于另一个静态库B的静态库A不会导致一个库从另一个库导出符号-B将不包含来自A的任何符号。

相反,您的构建系统将跟踪该依赖关系,并且一旦您进入链接器阶段(例如,通过构建依赖于B的可执行文件),构建系统就会注意 / em>库被链接。这也意味着,如果您没有构建系统或配置错误,即使链接到AB,也会因缺少C库中的符号而收到链接器错误。明确B

因此,规范的,可复制的符号复制方法需要通过动态库将它们拉入,因为这些库通过链接器。如果将CA更改为动态库,它们将与A链接,并包含来自A的各自独立的使用函数版本。如果在构建BC之间更改了B,它们将包含不同的定义。希望您的构建系统将尝试防止这种情况的发生。 请注意,关于动态库,C ++标准没有太多话要说,因此,有关如何在此处解析符号以及将产生重复符号的影响的技术性信息,请参阅您的操作系统手册。

使用MSVC,还可以对静态库执行此操作。在CYes的项目属性中,转到 Librarian -> General 并设置 Link Library Dependencies B.lib的选项。现在,如果您重建并再次查看C.libA的转储,它们也应包含B中的符号。当然,在生成结果可执行文件时,链接器将为每个版本分别从CA(或直接从A中选择版本,具体取决于您的链接方式)。 display.max_rows正在使用的符号。请不要在生产中这样做。