计算机系统篇之链接(18):如何避免未使用的且直接依赖的共享库

Author: stormQ

Created: Wednesday, 13. January 2021 08:38PM

Last Modified: Tuesday, 23. February 2021 12:06PM



摘要

本文主要描述了未使用的且直接依赖的共享库是如何产生的,以及一种如何避免的方法。


问题复现

step 1: 示例程序

hello.cpp:

int main()
{
  return 0;
}

step 2: 生成“有未使用的且直接依赖的共享库”的可执行目标文件 hello

$ g++ -Wl,--no-as-needed -g -o hello hello.cpp

在笔者机器上,g++ 的版本信息如下:

$ g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.049.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

step 3: 查看“未使用的且直接依赖的共享库”

$ ldd -u hello
Unused direct dependencies:
    /lib/x86_64-linux-gnu/libstdc++.so.6
    /lib/x86_64-linux-gnu/libm.so.6
    /lib/x86_64-linux-gnu/libgcc_s.so.1

产生原因

在一些较低版本的 gcc/g++ 编译驱动器中,并没有默认使用链接器选项--as-needed(该选项用于只链接需要的共享库)。所以,在生成可执行目标文件时,如果输入给链接器的共享库实际并不会使用(无论是系统共享库,还是第三方共享库),那么就会产生“未使用的且直接依赖的共享库”。

除此之外,在一些高版本的 gcc/g++ 编译驱动器中,如果禁用了默认的--as-needed功能(即添加了-Wl,--no-as-needed),也会产生“未使用的且直接依赖的共享库”。

至于如何判断 gcc/g++ 编译驱动器中是否默认提供--as-needed功能,可以使用-v选项查看编译的整个过程。

关于链接器选项--as-needed的相关代码提交见:


如何避免

至于如何避免未使用的且直接依赖的共享库,解决思路很直接:不将任何实际不使用的共享库作为链接器的输入。

对于第三方共享库,我们可以很简单地做到。然而,gcc/g++ 编译驱动器会默认将诸如libm.so等系统共享库作为链接器的输入。我们可以通过链接器选项-nodefaultlibs禁用这一行为。但,需要我们自己手动地添加需要的共享库,如下所示:

$ g++ -Wl,--no-as-needed -g -o hello hello.cpp -nodefaultlibs -lc
$ ldd ./hello
    linux-vdso.so.1 (0x00007fff397d3000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f70da02e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f70da23c000)

在使用-nodefaultlibs选项后,查看“未使用的且直接依赖的共享库”:

$ ldd -u ./hello
$

从上面的结果可以看出,现在不存在“未使用的且直接依赖的共享库”了。

关于链接器选项-nodefaultlibs的描述如下(截取自 《gcc 9.3 manual》):

Do not use the standard system libraries when linking. Only the libraries you
specify are passed to the linker, and options specifying linkage of the system
libraries, such as ‘-static-libgcc’ or ‘-shared-libgcc’, are ignored. The
standard startup files are used normally, unless ‘-nostartfiles’ is used.

其它相关的链接器选项:-nostartfiles-nolibc-nostdlib,有兴趣的可以参考 GCC 手册。


References


下一篇:计算机系统篇之异常控制流(4):如何正确地让调用线程休眠一段时间

上一篇:计算机系统篇之链接(17):"ldd: Unused direct dependencies" 意味着什么?

首页