根据ldd报告删除未使用的库是否完全安全?

时间:2011-05-09 08:17:30

标签: dynamic makefile g++ ld

我正在清理一个腐烂的源代码树,我尝试将每个可执行文件和每个共享库仅与它们直接使用的库链接。

为了做到这一点,我ldd -u- r二进制输出,并从makefile中删除报告的库。

例如:

$ ldd -u -r ./libA.so
Unused direct dependencies:
        /usr/local/lib/libB.so
        /usr/local/lib/libC.so
        /lib/tls/libpthread.so.0
$ sed -i'' -e 's/-lB//' -e 's/-lC//' Makefile

嗯,当然libpthread确实需要(并且无论如何都隐含在-pthread中),但ldd报告的其他库可以安全删除。

对我的优化有影响吗?它完全安全吗?

4 个答案:

答案 0 :(得分:6)

这是安全的*,除非发生一件事(谢天谢地,在你的控制之下)。

如果应用程序使用dlsym(RTLD_DEFAULT,...)加载其他符号,它将在当前加载的共享库中搜索相应的符号(函数)。如果它的意图是从你要删除的其中一个库中加载符号(没有先前的dlopen()调用),应用程序将找不到它,并且可能行为不端。

但请注意,dlsym()很少使用(并且您可以检查它是否通过ldd使用),而且如果没有事先调用dlopen(),它甚至更少使用它,所以几乎在所有情况下,您都可以安全地删除未使它将显着提高应用程序的可移植性。


* by“safe”我的意思是“如果没有构建时错误,可能会工作”。删除库的构建时间后果太容易检测到,无法解释它们。

答案 1 :(得分:2)

我能想到的一个含义是,可能存在仅由可执行文件使用的隐式依赖项,但是在库中指定。例如。

$ cat a.cc
int fa(){return 42;}
$ gcc -shared a.cc -o liba.so -ltermcap
$ cat main.cc
#include <stdio.h>
#include <stdlib.h>
#include <termcap.h>
int main() {
        tgetent(0,getenv("TERM"));
        printf("terminal is %d columns\n",tgetnum("co"));
}
$ gcc main.cc -o main # we didn't mention -ltermcap
/tmp/ccercfhS.o(.text+0x27): In function `main':
: undefined reference to `tgetent'
collect2: ld returned 1 exit status
$ # we mentioned -ltermcap by using -la
$ # if we'll remove -ltermcap from liba the project won't compile
$ gcc main.cc -o main -L. -la 
$ LD_LIBRARY_PATH=. ./main
terminal is 237 columns

然而,这并不是一个错误的错误,因为它总是会被您提前检测和修复,而不是由客户来检测。

无论如何,您应该include what you use因此,main.cctermcap直接关联是非常好的。

答案 2 :(得分:1)

如果我是你,我会使用strace进行一两次试运行

strace -e open myprog&gt; strace.out 2&gt;&amp; 1

然后检查strace输出以查看实际打开的库。这意味着任何不返回-1的open()调用。

答案 3 :(得分:0)

对我来说,似乎还有另外一个暗示,就是ldd将显示所有未找到的未使用的库(它们可能在构建时就已经存在,所以这里没有错误)。

所以,依靠ldd -u的结果并不安全!

(在Ubuntu Ubuntu 18.04.2下使用ldd 2.27和在Devuan ascii下使用ldd 2.24进行了测试)