Почему статически связывание glibc не рекомендуется?

Большинство онлайн-источников утверждают, что вы можете статически связывать glibc, но не рекомендуется делать это; например Репозиторий Centos:

The glibc-static package contains the C library static libraries
for -static linking.  You don't need these, unless you link statically,
which is highly discouraged.

Эти источники редко (или никогда) не говорят, почему это было бы плохой идеей.

Ответ 1

Причины, приведенные в других ответах, верны, но они не являются самой важной причиной.

Наиболее важная причина, по которой glibc не должен быть статически связан, заключается в том, что он широко использует dlopen для загрузки модулей NSS (переключателя службы имен) и iconv конверсии. Сами модули ссылаются на функции библиотеки C. Если основная программа динамически связана с библиотекой C, это не проблема. Но если основная программа статически связана с библиотекой C, dlopen должен загрузить вторую копию библиотеки C, чтобы удовлетворить требования к загрузке модулей.

Это означает, что вашей "статически связанной" программе по-прежнему требуется копия libc.so.6 для присутствия в файловой системе, плюс NSS или iconv или любых других модулей, а также других динамических библиотек, которые могут понадобиться модулям, таких как ld-linux.so.2, libresolv.so.2 и т.д. Это не то, чего обычно хотят люди, когда они статически связывают программы.

Это также означает, что статически связанная программа имеет две копии библиотеки C в своем адресном пространстве, и они могут бороться за то, чей буфер stdout должен использоваться, кто может вызвать sbrk с ненулевым аргументом, такого рода вещи, В glibc есть куча защитной логики, чтобы попытаться сделать это, но это никогда не гарантировалось.

Вы можете подумать, что вашей программе не нужно беспокоиться об этом, потому что она никогда не вызывает getaddrinfo или iconv, но поддержка локали использует iconv внутри, что означает, что любая функция stdio.h может вызвать вызов dlopen и вы не контролируете это, настройки переменных среды пользователя делают.

Ответ 2

Исправления ошибок в glibc не включаются в статически связанное приложение при обновлении glibc, если вы не перестраиваете приложение.

Кроме того, NSS (переключатель службы имен) не работает, если вы не используете динамическое связывание.

Ответ 3

Интерфейс программы /glibc стандартизирован и документирован стандартами POSIX, C и C++ и другими. Например, функция fopen() ведет себя в соответствии со стандартом C, а pthread_mutex_lock() - в POSIX.

Интерфейс glibc/ядра не стандартизирован. Использует ли fopen() open() под капотом? Или он использует openat()? Или что-то другое? Что он будет использовать в следующем году? Вы не знаете.

Если интерфейс glibc/ядра изменится, программа, которая использует все, что изменилось, но статически связывает glibc, больше не будет работать.

15+ лет назад, Solaris удалил все статические версии libc именно по этой причине.

Статическое связывание - куда оно делось?

С Solaris 10 вы больше не можете создавать статический исполняемый файл. Это не значит, что ld (1) не допускает статического связывания или использования архивов, просто библиотека libc.a, версия libc.so.1, больше не предоставляется. Эта библиотека обеспечивает интерфейсы между пользовательской средой и ядром, и без этой библиотеки довольно сложно создать приложение любой формы.

В течение некоторого времени мы предостерегали пользователей от статических ссылок, и ссылки на libc.a были особенно проблематичными. Каждый выпуск или обновление Solaris (даже некоторые исправления) приводили к сбою приложения, созданного на libc.a. Проблема в том, что libc должен изолировать приложение от границы пользователя/ядра, границы, которая может меняться от выпуска к выпуску.

Если приложение построено на основе libc.a, , то любой интерфейс ядра, на который он ссылается, извлекается из архива и становится частью приложения. Таким образом, это приложение может работать только на ядре, которое синхронизировано с используемыми интерфейсами ядра. В случае изменения этих интерфейсов приложение движется по шаткой почве.

...

Изменить:

Кажется, существует серьезная переоценка стабильности интерфейса ядра Linux. Подробности смотрите в Изменениях/дополнениях API ядра Linux. Подводя итог:

enter image description here