Полностью ли безопасно удалить неиспользуемые библиотеки, как сообщает ldd? - PullRequest
3 голосов
/ 09 мая 2011

Я очищаю загнившее дерево исходников и пытаюсь сделать каждый исполняемый файл и каждую общую библиотеку связанными только с библиотеками, которые они используют напрямую.

Чтобы сделать это, я ldd -u- r выдает двоичный вывод и удаляю сообщаемые библиотеки из make-файла.

Например:

$ 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 ]

6 голосов
/ 09 мая 2011

Это безопасно *, если ничего не происходит (что, к счастью, под вашим контролем).

Если приложение загружает дополнительные символы с помощью dlsym(RTLD_DEFAULT,...), оно будет искать в загруженных общих библиотеках соответствующий символ (функцию). Если он предназначен для загрузки символа из одной из этих библиотек, которую вы хотите удалить ( и не было предшествующего вызова dlopen()), приложение не найдет его и может работать неправильно.

Обратите внимание, однако, что dlsym() используется очень редко (и вы можете проверить, используется ли он через ldd), и еще реже использовать его без предварительного вызова dlopen(), поэтому почти во всех случаях безопасно удалить неиспользуемые библиотеки. Это значительно улучшит переносимость вашего приложения.


* под «безопасным» я подразумеваю «вероятно, сработает, если не было ошибок во время сборки». Последствия удаления библиотек во время сборки слишком легко обнаружить, чтобы учесть их.

2 голосов
/ 09 мая 2011

Одно из следствий, о котором я могу думать, это то, что может существовать неявная зависимость, которая используется только исполняемым файлом, но указывается в библиотеке. Например.

$ 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

Однако это не такая уж и плохая ошибка, поскольку она всегда будет обнаруживаться и исправляться вами, а не клиентами.

И вообще, вам следует включить то, что вы используете , поэтому очень хорошо иметь main.cc ссылку с termcap напрямую.

1 голос
/ 14 июля 2011

Если бы я был вами, я бы сделал один или два тестовых прогона, используя strace, например:

strace -e, откройте myprog> strace.out 2> & 1

Затем проверьте выход Strace дляпосмотреть, какие библиотеки на самом деле открыты.Это означает, что любой вызов open () не возвращает -1.

0 голосов
/ 13 июня 2019

Мне кажется, что ldd будет отображать все библиотеки, которые он не может найти, как неиспользуемые (они могли быть там во время сборки, поэтому здесь нет ошибок).

Итак нет , на результаты ldd -u!

небезопасно (тестируется с ldd 2.27 под Ubuntu Ubuntu 18.04.2 и ldd 2.24 под Devuan ascii)

...