Статические библиотеки C осуждаются? [закрыто]

11

Есть 2 аргумента для наличия общих библиотек:

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

У разделяемых библиотек есть в основном один недостаток:

  • Они (могут) ввести ад зависимости.

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

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

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


Поскольку одно из главных преимуществ разделяемых библиотек больше не имеет большого значения, все еще не одобряются статические библиотеки C? Если так, то почему?

Флориан Маргейн
источник
4
Основная причина, по которой С используется больше, заключается именно в том, что вы не работаете на современных настольных компьютерах.
Теластин
18
@ Теластин, прости? Большая часть программного обеспечения, установленного на моих настольных компьютерах, написана на C.
Florian Margaine
6
Побочный бит - прочтение сайта на эту тему - Динамические
6
Одним из преимуществ динамических библиотек является то, что люди все еще могут обновлять библиотеки, чтобы обойти ошибки, дыры в безопасности или проблемы с оборудованием в вашей 15-летней игре с закрытым исходным кодом, которая давно перестала получать обновления. В некотором роде нишевый случай, но поскольку хорошие игры не являются товаром, «просто используйте другую программу» не очень помогает. Это также имеет значение для соответствия LGPL без открытого поиска собственного кода.
Довал
4
Вы забыли о двух других преимуществах разделяемых библиотек: 1) они тоже разделяются в памяти, 2) все линкеры плохо сосут, и связывание огромного двоичного файла крайне неприятно. Разделение двоичного файла на несколько более мелких объектов делает весь процесс гораздо более терпимым.
SK-logic

Ответы:

9

Предпосылка вашего вопроса ошибочна. То, что осуждается, - это придерживаться доктринеров и абсолютов, не понимая их основ (программирование грузового культа?).

Связанный ответ SO является интересным исследованием в этой самой теме - Вопрос был о том, почему не работает опция компиляции с -static, а ответ, на который вы ссылались, был не более чем разглагольствованием о том, что не используется статическое связывание. Если не обсуждает, почему это плохо, а требует, то ОП использует динамическое связывание. К сожалению, он помечен как правильный ответ (следующий ответ имеет в два раза больше голосов и является правильным ответом на вопрос ОП), потому что, хотя правильный ответ есть, он глубоко скрыт в догматическом мнении.

Реальный вопрос заключается в том, каковы плюсы и минусы статического и динамического связывания, и когда один из них предпочтительнее другого.

mattnz
источник
2
Ответ Basile в действительно сказать вам точно , почему он рекомендует использовать разделяемые библиотеки: ? «Почему вы хотите , чтобы ссылка статически ваше приложение . Как правило , это ошибка (потому что вы не прибыли от обновлений для системы динамических библиотек) В частности , переключатель службы имен средства из libc хотят динамические библиотеки. " Это не" напыщенная речь "только потому, что вы не согласны с этим.
Коди Грей
@Cody Ответ, связанный с, был отредактирован, так как я назвал его напыщенной. Единственное мнение, которое я придерживаюсь статического и динамического связывания, - это использовать то, что соответствует вашим потребностям, и понять сильные и слабые стороны этого выбора, а не попадать в доктрину программирования культа грузов, потому что «кто-то так сказал».
Mattnz
Да, часть "В частности ..." была добавлена. Не уверен, как это влияет на его статус разглагольствования. Конечно, я не поддерживаю программирование культа грузов. Просто сторонники статического связывания (по моему опыту) часто пропускают или недооценивают проблемы безопасности. Статическое связывание может быть очень подходящим для одноразовых утилит, что делает приложение автономным и, следовательно, его распространение намного проще. Но любое приложение, которое будет широко развернуто или использовано для производства, должно действительно ссылаться на общую библиотеку. Нет никаких реальных недостатков: на этом уровне приложения вам уже нужен процесс развертывания.
Коди Грэй,
1
Хороший пример того, где уместно статическое связывание, - это то, где я работаю - большие, сложные жизненно важные системы. После того, как критический модуль протестирован и одобрен для работы, его поведение не должно меняться без прохождения «процесса». Однако никакие операционные и не жизненно важные части системы (выставление счетов и отчетность) не требуют менее надежного управления и используют динамическое связывание.
Mattnz
7

С точки зрения разработчика, динамическое связывание часто может значительно ускорить ваш цикл компиляции / ссылки / тестирования.

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

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

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

Карл Билефельдт
источник
2
Это правда (ускорение разработки), но очень неприятно, что он превращает его в производство. Каноническим примером является Firefox. Количество инженерных усилий (в виде отвратительных взломов), которые пошли на ускорение динамического разрешения символов ссылок, так что Firefox загружается в разумные сроки, совершенно безумно. Гораздо лучшая производительность могла бы быть достигнута при гораздо меньших затратах на разработку, если бы они просто хотели статически связывать весь свой код в проекте (при этом динамически связывая системные библиотеки и плагины, если это необходимо).
R .. GitHub ОСТАНОВИТЬ ПОМОЩЬ ЛЬДУ
5

Общие библиотеки сильно предпочитает Linux распределение сопровождающих для вашей основном причины # 2. Для них действительно важно, что, например, когда кто-то находит ошибку безопасности в zlib , ему не нужно перекомпилировать каждую из программ, использующих zlib - не только это будет стоить им больше циклов ЦП для выполнения после перекомпиляции каждый, кто использует дистрибутив, должен будет заново загрузить все эти программы. Между тем, в наборе пакетов, предоставляемых дистрибутивом, ад зависимости не является проблемой, потому что все проверено на работу с этим набором библиотек.

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

Другая важная вещь, которую нужно знать, это то, что GNU libcи GCC libstdc++имеют компоненты, которые не работают надежно, если библиотека статически связана. Наиболее распространенная проблема связана с dlopenтем, что любой загружаемый модуль dlopenсам по себе динамически связан с libc.so.6. Таким образом, это означает, что теперь у вас есть две копии библиотеки C в вашем адресном пространстве, и веселье наступает, когда они не соглашаются с тем, какая копия внутренней mallocструктуры данных (например) является авторитетной. Становится все хуже: целая куча функций , которые , кажется , не имеет ничего общего с dlopen, как gethostbynameи iconv, использоватьdlopenвнутренне (так что их поведение настраивается во время выполнения). К счастью, ABI для libc и libstdc ++ очень стабилен, поэтому вы вряд ли столкнетесь с проблемами их динамического связывания.

zwol
источник
2

Я согласен с последним замечанием Мэтнза: этот вопрос - загруженный вопрос. Предполагается, что статическое связывание плохое. Я могу думать о двух причинах, почему это не так:

  • Статическое связывание является безопасным: если общая библиотека обновляется таким образом, что приложение использует новую (возможно, новая перезаписывает старую или удаляется старая), это может создать риск того, что новая версия сломает приложение. Это изменение кода выходит за рамки официального обновления для приложения. Это, возможно, не было проверено. Статическое связывание обходит стороной, не разделяя библиотеки извне. Я считаю, что это является недостатком для разделяемых библиотек из-за этого риска. Что, если новая версия общей библиотеки представляет новую ошибку, которая ломает некоторые старые приложения?

  • Статическое связывание гарантирует, что приложение более автономно. Хотя совместно используемые библиотеки можно размещать вместе с основным исполняемым файлом, часто они хранятся в общих местах. Статически связанные приложения легче обеспечить «переносимыми» в смысле «не требующих изменений в файлах, каталогах или настройках, принадлежащих ОС» (например, каталог Windows, реестр и т. Д.).


источник
Спасибо за улучшение преимуществ, которые я хотел упомянуть. Однако, если вы видите, например, большинство пакетов, предоставляемых дистрибутивами Linux, они не компилируются статически. Это действительно кажется , что статическая компиляция неодобрения, по крайней мере , с внешней точки зрения.
Флориан Маргэйн
1
Динамические библиотеки практически во всех операционных системах в настоящее время доступны по требованию. Только фактически используемые страницы находятся в памяти. Если несколько приложений используют одну и ту же функциональность, они будут совместно использовать память и использовать меньше, чем в случае статической библиотеки. Если несколько приложений используют разные функциональные возможности в одной и той же библиотеке, оба набора функциональных возможностей будут разбиты на страницы, что будет иметь примерно то же влияние, что и статический подход.
Алан Шутко
@AlanShutko Я боролся и перепечатал эту часть несколькими способами из-за того, что вы упомянули. В любом случае нет никаких реальных гарантий, даже если современные операционные системы на практике предлагают эффективность разделяемых библиотек с издержками статического. Я буду редактировать снова.
@ Снеговик Я думаю, что основной момент заключается в том, что в любой реалистичной операционной системе, которая обеспечивает динамическое связывание (я не знаю ни одной ОС, которая использует динамическое связывание, но не требует подкачки страниц), ваша вторая точка не выдерживает критики: память фактически не используется если функция не используется, а память, используемая динамической библиотекой, может быть разделена между различными программами, использующими ее, что делает использование памяти для динамической версии более эффективным, а не меньшим. Ваши первая и третья причины верны, но я бы просто удалил вторую: с любыми реалистичными предположениями это просто неправильно.
Жюль
@ Джулс Я согласен, это вопрос, который был проблематичным и сомнительным в современных операционных системах. Я удалил это.
1

Статические и динамические библиотеки имеют свое использование. Глядя на одно приложение по объему, мы получаем другое представление о том, что необходимо, а что нет.

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

Очевидным преимуществом динамических библиотек является возможность применять обновления независимо.

Это одна из причин, по которой я ненавижу maven и других подобных динамических компоновщиков компоновок проектов для java. Они ожидают, что одна версия библиотеки будет доступна по заданному URL навсегда. Непонимание проблемы, которая возникает через 10 лет, когда никто не может скомпилировать приложение, потому что все исходники и файлы jar пропали.

много чипсов
источник
Есть ли какая-то конкретная причина, по которой для программ, которые используют FooLib1.8такую ​​возможность, невозможно включить код этой библиотеки в свой исполняемый пакет стандартным способом, чтобы позволить поставляемой вместе с ней утилите FooLib1.9обновления обновить или понизить ее версию? Способ хранения кода в Classic Macintosh сделал бы это довольно легко; есть ли причина, по которой сегодняшние системы не могут сделать это еще лучше?
суперкат
@supercat Вы имеете в виду, что каждая версия данной библиотеки будет доступна в системе? Не уверен, что понимаю вопрос. Вопрос OP был направлен больше на общесистемные общие библиотеки, чем на статические библиотеки, которые будут упакованы вместе.
много чипсов
Я хотел сказать, что наличие в исполняемом пакете всех необходимых библиотек не должно исключать возможность обновления содержащихся в нем библиотек. Таким образом, я не знаю, что я бы рассматривал возможность обновления вещей после развертывания как преимущество не связывать приложение с его библиотеками.
суперкат
Если лицензия данной библиотеки позволяет вам распространять ее вместе с вашим пакетом, то это всегда предпочтительный способ сделать это. Это уменьшает количество внешних зависимостей. Поскольку вы будете распространять все, то механика обновления или исправления будет работать так же со статическим или динамическим. Исправления обычно основаны на двоичных дельтах. Там не было бы никакой разницы.
много чипсов