静态和动态库链接

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() 函数,因此您会收到相应的错误。

【讨论】:

以上是关于静态和动态库链接的主要内容,如果未能解决你的问题,请参考以下文章

动态链接库和静态链接库

C语言里面的动态库和静态库

如何使用cmake生成基于静态库的动态链接库

关于动态库和静态库的问题。

静态链接库和动态链接库

动态链接库和静态链接库的区别