4

我从来没有想过下面的问题,但是因为我现在不得不处理我的代码中的一堆依赖项,所以我认为我最好把我的事实弄清楚。让我们将其限制为现代 Linux 版本,比如 ubuntu amd64。

由于静态库不包含动态库引用,如何在静态库中解析未定义的符号?依赖二进制文件可以动态加载未定义的符号,还是必须在编译时由另一个静态库或目标文件解析符号?

编译器是否可以通过链接动态库来解决依赖关系(依赖于静态库的应用程序),如果是这样,代码文本是否会通过静态解析到生成的二进制文件中,或者是否存在动态引用?

例如,静态库L使用mallocfromlibc6.so并将由 application 使用A。是否会动态使用 libc6.soLA的 malloc?

4

2 回答 2

7

静态库只不过是一起归档的目标文件列表。

如何在静态库中解析未定义的符号?

它们没有被解析,因为没有未定义的符号。符号仅在链接阶段被认为是未定义的,并且在创建静态库时不会进行链接。

当您将二进制文件链接到静态库时,可能存在未定义的符号。在这种情况下,静态库被视为程序的一部分,因此对该静态库中使用的符号的所有引用都必须在您构建的程序范围内可用。比如说,如果程序与使用来自其他库的符号A的静态库链接,则程序必须与and链接。BCDABD

依赖二进制文件可以动态加载未定义的符号吗

是的,它可以。但是除非你真的需要懒惰的动态分辨率,否则你不应该这样做。

或者必须在编译时由另一个静态库或目标文件解析符号

目标文件以及静态库不解析任何符号。是链接器执行此操作。

愿编译器解决...

编译器不解析任何依赖项。这是链接器的工作。依赖关系可以在链接时解决,或者在运行时通过动态链接器解决。

通过链接到动态库来依赖(依赖于静态库的应用程序),...

链接器可以理解您使用的静态库取决于您链接的动态库中的符号。

如果是这样,代码文本将静态解析为生成的二进制文件还是存在动态引用?

如果您链接到一个共享库,那么您的程序中将不会有任何静态可用的内容。这就是共享库的意义所在。唯一的例外是 LTO。至于您链接的静态库,该静态库中的任何内容都不会动态可用,它会被编译,并且那些未使用的符号将被消除。

例如,静态库 L 使用 libc6.so 中的 malloc,应用程序 A 将使用它。L 和 A 是否都动态使用 libc6.so 中的 malloc?

是的,除非在malloc()编译静态库时定义是可用的,并且由于某种原因编译器只是将 的主体内联malloc()到静态库的代码中。但malloc()它不会发生。不过可能会遇到其他功能。

于 2012-03-07T17:16:21.307 回答
1

一个静态库(一个foo.a文件)实际上是一堆目标文件(xoyo,...),其中包含归档程序ar 。

这个静态库在链接时使用,以满足其他未定义的引用。在链接时不满足的所有内容(编译时间在这里并不重要),必须在加载时通​​过动态库(bar.so文件)来满足。

在您的最后一个示例中,使用静态库 L 和程序 A,(A,L)都将使用 libc6.so 中的相同 malloc,只要您不使用可能来自不同头文件或其他技巧的预加载、内联 malloc ,你没有提到。

于 2012-03-07T17:09:02.277 回答