这是我的解决方案的结构:
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
)检查嵌入到结果应用程序中的代码。事实证明,B
和C
库使用A
库的唯一实例。有什么方法(出于教育目的)在A
和B
中使用C
的两个不同实例?也许对于这个东西有链接器的特定选择?我了解,这种行为可能会产生意想不到的副作用,这取决于A
库的逻辑。
P.S。我通过在项目属性中直接包含.lib文件来替换对项目的引用。现在B
,C
个项目有一个A
项目的副本。但是最终项目仍具有A
库的唯一副本。我不知道链接程序如何解决这个问题。
答案 0 :(得分:4)
首先,如果最终在构建中遇到两个A
实例,则从A
导出的所有标识符都必须遵循One-Definition-Rule。
也就是说,即使您在技术上可以拥有A
的两个不同版本,除非它们在所有意图和目的上都是相同的,否则您的程序是无效的,并且编译器和链接器都没有义务告诉您( C ++标准将其称为格式错误,无需诊断)。实际上,这意味着您的程序中将有很多个怪异的bug,并且不知道它们来自何处。
话虽如此,从技术上讲,没有什么可以阻止您构造类似您所要求的情况。通常,静态依赖项仅在链接阶段进行处理。因此,依赖于另一个静态库B
的静态库A
不会导致一个库从另一个库导出符号-B
将不包含来自A
的任何符号。>
相反,您的构建系统将跟踪该依赖关系,并且一旦您进入链接器阶段(例如,通过构建依赖于B
的可执行文件),构建系统就会注意 / em>库被链接。这也意味着,如果您没有构建系统或配置错误,即使链接到A
和B
,也会因缺少C
库中的符号而收到链接器错误。明确B
。
因此,规范的,可复制的符号复制方法需要通过动态库将它们拉入,因为这些库通过链接器。如果将C
和A
更改为动态库,它们将与A
链接,并包含来自A
的各自独立的使用函数版本。如果在构建B
和C
之间更改了B
,它们将包含不同的定义。希望您的构建系统将尝试防止这种情况的发生。
请注意,关于动态库,C ++标准没有太多话要说,因此,有关如何在此处解析符号以及将产生重复符号的影响的技术性信息,请参阅您的操作系统手册。
使用MSVC,还可以对静态库执行此操作。在C
或Yes
的项目属性中,转到 Librarian -> General 并设置 Link Library Dependencies B.lib
的选项。现在,如果您重建并再次查看C.lib
和A
的转储,它们也应包含B
中的符号。当然,在生成结果可执行文件时,链接器将为每个版本分别从C
或A
(或直接从A
中选择版本,具体取决于您的链接方式)。 display.max_rows
正在使用的符号。请不要在生产中这样做。