静态和动态库链接
Posted
技术标签:
【中文标题】静态和动态库链接【英文标题】:Static and dynamic library linking 【发布时间】:2010-09-15 04:50:01 【问题描述】:在 C++ 中,静态库 A 链接到动态库 B 和 C。如果在 B 中定义的 A 中使用了类 Foo,如果不使用 Foo,C 会链接吗?
我认为答案是肯定的,但是我现在遇到了 xlc_r7 的问题,其中库 C 说 Foo 是一个未定义的符号,就 C 而言它是一个未定义的符号。我的问题是库 C 没有使用引用它的类。此链接在 Win32 (VC6) 和 OpenVMS 中。
这是链接器差异还是 PBCAK?
新信息:
B 依赖于 C,但反之亦然。
我没有使用 /OPT:REF 在 Windows 上进行链接,它可以毫无问题地链接。
【问题讨论】:
根据 msdn,LINK 默认会删除未引用的打包函数(就像您使用 /OPT:REF 一样)。 【参考方案1】:当您静态链接时,两个模块合二为一。所以当你编译C并将A链接到其中时,就好像你已经将A的所有源代码复制到了C的源代码中,然后编译了组合的源代码。所以 C.dll 包含 A,它通过 Foo 依赖于 B。您需要将 C 链接到 B 的链接库以满足该依赖关系。
请注意,根据您的信息,这将在 B 和 C 之间创建循环依赖。
【讨论】:
【参考方案2】:听起来它可能是链接器(ld/unix),因为(我使用过的大多数版本)ld 从左到右链接库 - 如果第一个引用中需要由稍后,通常的技巧是将第一个库(或任何必需的库)附加到命令的末尾。
试试看吧....
【讨论】:
xlc 的链接器比较棘手,虽然...从左到右的链接线大部分都可以工作,但实际上,所有内容都加载到内存中,然后进行图形遍历以满足链接。它比旧式链接更贵,但链接线不必订购。它也以有趣的方式打破 我认为这不是问题,因为 1. 我尝试了不同的顺序和 2. Foo 未被任何其他库使用。【参考方案3】:您的 C 链接行是否包含 B 的导出库?如果是这样,那么就像理查德所说的那样,这听起来像是一个订购的东西。
另一个建议是看看是否有一个链接器选项来忽略未引用的符号,如果 C 不需要来自 A 的功能。对于 Microsoft 链接器,这是通过 /OPT:REF 开关实现的。
【讨论】:
【参考方案4】:C 不链接的唯一原因是编译器认为它确实需要 Foo 符号。
由于 C 不引用 Foo 符号,因此链接器需要该符号肯定还有另一个原因。
我知道的唯一其他原因是某种出口。我只知道 Visual C++,所以我建议你在预处理文件中搜索 __declspec( dllexport )
的等价物,看看是什么生成的。
这就是我要做的:将预处理器输出存储在一个单独的文件中,并在其中搜索 Foo.它要么作为导出出现,要么被编译器以某种方式引用。
【讨论】:
我已经在寻找我错过的任何东西。 Foo 仅由 A 中的一个类在 C 不包含的文件中使用。所涉及的所有类都没有被导出。链接器抱怨 Foo 中的特定方法,例如Foo::DoThis() Foo::DoThat()。【参考方案5】:如果不需要定义特定函数,则在链接阶段不会链接该库。在您的情况下,由于 foo 的定义存在于库 B 中,而不存在于库 C 中。因此,在加载可执行文件时,库 C 不会被加载到内存中。
但您似乎也在使用库 C 中的 foo() 函数,因此您会收到相应的错误。
【讨论】:
以上是关于静态和动态库链接的主要内容,如果未能解决你的问题,请参考以下文章