通过两次链接同一个库来解决循环依赖关系
Resolving circular dependencies by linking the same library twice?
我们有一个分解为静态库的代码库。不幸的是,这些库具有循环依赖关系;例如libfoo.a
取决于libbar.a
,反之亦然。
我知道处理这个问题的"正确"方法是使用链接器的--start-group
和--end-group
选项,如下所示:
g++ -o myApp -Wl,--start-group -lfoo -lbar -Wl,--end-group
但在我们现有的Makefile中,问题通常是这样处理的:
g++ -o myApp -lfoo -lbar -lfoo
(想象一下,这扩展到大约20个具有复杂相互依赖性的库。)
我一直在查看我们的Makefile,将第二种形式更改为第一种形式,但现在我的同事问我为什么。。。除了"因为它更干净"和模糊地认为另一种形式有风险之外,我没有一个好的答案。
那么,多次链接同一个库是否会产生问题?例如,如果相同的.o被拉入两次,那么多重定义符号的链接会失败吗?或者,我们有没有可能最终得到同一静态对象的两个副本,从而产生微妙的错误?
基本上,我想知道多次链接同一个库是否可能导致链接时间或运行时故障;如果是,如何触发它们。谢谢
的问题
g++ -o myApp -lfoo -lbar -lfoo
不能保证在libfoo
上两次通过和在libbar
上一次通过就足够了。
Wl,--start-group ... -Wl,--end-group
的方法更好,因为它更健壮。
考虑以下场景(所有符号都在不同的对象文件中):
- CCD_ 8需要在CCD_ 10中定义的符号CCD_
- 符号
fooA
需要在libbar
中定义的符号barB
- 符号
barB
需要在libfoo
中定义的符号fooC
。这是循环依赖关系,可以由-lfoo -lbar -lfoo
处理 - 符号
fooC
需要在libbar
中定义的符号barD
为了能够在上面的情况下进行构建,我们需要将-lfoo -lbar -lfoo -lbar
传递给链接器。为什么?
- 链接器第一次看到
libfoo
,并使用符号fooA
的定义,但不使用fooC
,因为到目前为止,它认为没有必要将fooC
也包括在二进制中。然而,链接器开始寻找barB
的定义,因为fooA
的功能需要它的定义 - 链接器看到
-libbar
,包括barB
的定义(但不是barD
),并开始寻找fooC
的定义 fooC
的定义在第二次处理时在libfoo
中找到。现在很明显,也需要barD
的定义——但命令行上再也没有libbar
了,太晚了
上面的例子可以扩展到任意的依赖深度(但这种情况在现实生活中很少发生)。
因此使用
g++ -o myApp -Wl,--start-group -lfoo -lbar -Wl,--end-group
是一种更稳健的方法,因为链接器根据需要经常通过库组——只有当一次传递没有改变符号表时,链接器才会在命令行上移动到下一个库。
然而,要付出的性能代价很小:在第一个示例中,与手动命令行-lfoo -lbar -lfoo
相比,-lbar
被再次扫描。不确定它是否值得一提/仔细思考。
我所能提供的只是缺少反例。事实上,我以前从未见过第一种形式(尽管它显然更好),总是看到第二种形式解决了这个问题,因此也没有观察到问题。
即便如此,我仍然建议更改为第一种形式,因为它清楚地显示了库之间的关系,而不是依赖于链接器以特定的方式运行。
也就是说,我建议至少考虑一下是否有可能重构代码,将常见的部分提取到其他库中。
由于它是一个遗留应用程序,我敢打赌库的结构是从一些可能不再重要的排列中继承的,例如用于构建另一个您不再做的产品。
即使继承的图书馆结构仍然存在结构性原因,几乎可以肯定的是,从遗留安排中再建造一个图书馆仍然是可以接受的。只需将20个库中的所有模块放入一个新库liballofthem.a
即可。那么每个应用程序都是简单的g++ -o myApp -lallofthem ...
- Ardunio UNO解决了多个重叠的定时器循环
- 在java中解决这段代码时面临循环中的问题
- 循环无限运行C++解决骑士之旅问题
- 是否有可能实现O(N)时间和O(1)空间解决方案,以实现C++中的字符串循环移位
- 在包含窗口标头时难以解决循环依赖关系问题
- C++ 而循环问题 Codecademy 参考 [已解决]
- 解决循环依赖关系 c++ 的想法
- 解决C++中 3 个类的循环包含
- C++ 循环屏障中的倒计时使用原子变量出错[请无锁的解决方案]
- 为什么使用 2 个嵌套循环 O(n^2) 复杂度来解决二和问题,当只改变循环计数器逻辑时运行得更快?
- "invalid use of incomplete type" .解决循环依赖关系
- 将成员对象更改为指针以解决循环依赖性
- C++正在创建一个头来解决循环依赖关系,这是一个好主意
- C++是否有解决循环依赖的方法
- C++使用一个模板解决循环依赖关系
- 视觉C++在解决循环依赖关系时遇到了设计问题
- 通过两次链接同一个库来解决循环依赖关系
- 正在解决循环依赖关系
- 为什么前向声明和指针(或引用?)可以解决循环依赖
- 当向前声明不可能尽可能优雅时,我如何解决循环类依赖