Является ли исполняемый файл, построенный по-разному, если он связан с библиотекой, которая не используется?

Помимо более длительного времени компиляции, существует ли недостаток для связывания с неиспользуемой библиотекой?

например, есть ли какая-либо разница в исполняемом файле программы, которая скомпилирована одним из двух способов:

g++ -o main main.cpp
g++ -o main main.cpp -llib1 -llib2 -llib3 -lmore

* для создания основного файла на самом деле не нужны файлы библиотеки.

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

Ответ 1

Это зависит.

  • Если liblib1.a, liblib2.a и liblib3.a являются статическими библиотеками, и из них не используются никакие символы, тогда разница не будет.

  • Если liblib1.so, liblib2.so или liblib3.so являются общими библиотеками, то они будут загружаться во время выполнения независимо от того, используются они или нет. Вы можете использовать флаг компоновщика --as-needed, чтобы изменить это поведение, и этот флаг рекомендуется.

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

$ cat main.c
int main()
{
    return 0;
}
$ gcc main.c
$ readelf -d a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
$ gcc -lpng main.c
$ readelf -d a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libpng12.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Вы можете видеть, что в моей системе -lpng ссылки на libpng12.so.0, действительно ли используются символы из нее. Флаг компоновщика --as-needed исправляет это:

$ gcc -Wl,--as-needed -lpng main.c
$ readelf -d a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Примечания

  • Флаг --as-needed должен быть указан перед библиотеками. Это влияет только на библиотеки, которые появляются после него. Поэтому gcc -lpng -Wl,--as-needed не работает.

  • Команда ldd отображает не только библиотеки, с которыми связаны ваши двоичные файлы, но и все косвенные зависимости. Это может измениться в зависимости от того, как были скомпилированы эти библиотеки. Только readelf покажет вам ваши прямые зависимости, и только ldd покажет вам косвенные зависимости.

Ответ 2

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

Ответ 3

Абсолютно да. Недостатком является то, что другие (или вы в будущем) предполагают, что по какой-то причине необходимы библиотеки . Большинство людей не будет тратить время на зависание программных зависимостей, и поэтому их список растет и растет.

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

Ответ 4

Есть несколько действительно хороших ответов выше. Еще одно замечание - "какая разница, действительно ли это делает". Уже упоминается стоимость обслуживания (например, проблемы, когда кто-то устанавливает новую операционную систему, у которой нет Lib3, поэтому пользователь должен где-то найти lib3 и установить его, а поскольку lib3 также нуждается в lib17, который вы также не используете установлен, он добавляет больше работы для пользователя).

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

Как только код загружен, он не должен иметь дополнительного штрафа во время выполнения.

Сказав это, иногда существуют аргументы для связывания с неиспользуемыми библиотеками. Скажем, у вашего кода есть опция USE_FOO, где функция FOO включена только в зависимости от произвольного выбора при построении (например, "это на ядре Linux > 3.0" или "Есть ли у системы привлекательная графическая карта" ), а FOO использует Lib1 чтобы сделать это бизнес, он может сделать систему сборки (makefile или аналогичную) немного проще, чтобы всегда ссылаться на lib1, даже если вам это действительно не нужно, когда USE_FOO не установлен.

Но в целом, не связывайтесь с библиотеками, которые вам не нужны. Это вызывает больше зависимостей, и это никогда не бывает хорошо.