При создании библиотеки классов в C ++ вы можете выбирать между динамическими ( .dll
, .so
) и статическими ( .lib
, .a
) библиотеками. В чем разница между ними и когда уместно использовать какие?
c++
dll
shared-libraries
static-linking
dynamic-linking
Мортен Кристиансен
источник
источник
Ответы:
Статические библиотеки увеличивают размер кода в вашем двоичном файле. Они всегда загружаются, и любая версия кода, с которой вы скомпилировали, является версией кода, который будет работать.
Динамические библиотеки хранятся и версии отдельно. Возможно загрузить версию динамической библиотеки, которая не была оригинальной, поставляемой с вашим кодом, если обновление считается двоичным, совместимым с исходной версией.
Кроме того, динамические библиотеки не обязательно загружаются - они обычно загружаются при первом вызове - и могут быть разделены между компонентами, которые используют одну и ту же библиотеку (несколько загрузок данных, одна загрузка кода).
Динамические библиотеки считались лучшим подходом в большинстве случаев, но изначально у них был серьезный недостаток (ад Google gll DLL), который был почти полностью устранен более поздними операционными системами Windows (в частности, Windows XP).
источник
Другие адекватно объяснили, что такое статическая библиотека, но я хотел бы указать на некоторые предостережения об использовании статических библиотек, по крайней мере, в Windows:
Singletons: Если что-то должно быть глобальным / статическим и уникальным, будьте очень осторожны, помещая это в статическую библиотеку. Если несколько статических библиотек связаны с этой статической библиотекой, каждая из них получит свою собственную копию синглтона. Однако, если ваше приложение представляет собой один EXE-файл без пользовательских DLL, это может не быть проблемой.
Удаление кода без ссылок: Когда вы ссылаетесь на статическую библиотеку, только те части статической библиотеки, на которые ссылается ваша DLL / EXE, будут связаны с вашей DLL / EXE.
Например, если
mylib.lib
содержитa.obj
иb.obj
и ваша DLL / EXE ссылается только на функции или переменные изa.obj
,b.obj
компоновщик полностью отбрасывает их. Еслиb.obj
содержит глобальные / статические объекты, их конструкторы и деструкторы не будут выполнены. Если эти конструкторы / деструкторы имеют побочные эффекты, вы можете быть разочарованы их отсутствием.Аналогично, если статическая библиотека содержит специальные точки входа, вам, возможно, потребуется позаботиться о том, чтобы они действительно были включены. Примером этого во встроенном программировании (хорошо, не в Windows) будет обработчик прерываний, который помечен как определенный адрес. Вам также нужно пометить обработчик прерываний как точку входа, чтобы убедиться, что он не сбрасывается.
Другим следствием этого является то, что статическая библиотека может содержать объектные файлы, которые невозможно использовать из-за неразрешенных ссылок, но это не вызовет ошибку компоновщика, пока вы не обратитесь к функции или переменной из этих объектных файлов. Это может произойти спустя много времени после написания библиотеки.
Символы отладки: вам может потребоваться отдельная PDB для каждой статической библиотеки, или вы можете захотеть, чтобы символы отладки помещались в объектные файлы, чтобы они попадали в PDB для DLL / EXE. Документация по Visual C ++ объясняет необходимые параметры .
RTTI: Вы можете получить несколько
type_info
объектов для одного и того же класса, если объедините одну статическую библиотеку в несколько библиотек DLL. Если ваша программа предполагает, чтоtype_info
это «единичные» данные и использует&typeid()
илиtype_info::before()
, вы можете получить нежелательные и неожиданные результаты.источник
Библиотека - это единица кода, которая входит в состав исполняемого файла вашего приложения.
DLL - это автономная единица исполняемого кода. Он загружается в процессе только тогда, когда вызов сделан в этот код. DLL может использоваться несколькими приложениями и загружаться в нескольких процессах, при этом на жестком диске остается только одна копия кода.
Dll плюсы : могут быть использованы для повторного использования / обмена кодом между несколькими продуктами; загружать в память процесса по требованию и может быть выгружен при необходимости; может быть обновлен независимо от остальной части программы.
Недостатки DLL : влияние на производительность загрузки DLL и перебазирование кода; проблемы с версиями ("dll hell")
Lib плюсы : не влияет на производительность, так как код всегда загружается в процессе и не перебазируется; нет проблем с версиями.
Lib cons : исполняемый файл / процесс «раздувать» - весь код находится в вашем исполняемом файле и загружается при запуске процесса; нет повторного использования / обмена - каждый продукт имеет свою собственную копию кода.
источник
Помимо технических последствий использования статических и динамических библиотек (статические файлы объединяют все в один большой двоичный файл и динамические библиотеки, которые обеспечивают совместное использование кода несколькими различными исполняемыми файлами), существуют юридические последствия .
Например, если вы используете лицензионный код LGPL и статически связываетесь с библиотекой LGPL (и, таким образом, создаете один большой двоичный файл), ваш код автоматически становится кодом LGPL с открытым исходным кодом ( бесплатно как в свободе) . Если вы ссылаетесь на общие объекты, то вам нужно только LGPL улучшить / исправить ошибки, которые вы вносите в саму библиотеку LGPL.
Это становится гораздо более важной проблемой, если вы решаете, например, как скомпилировать ваши мобильные приложения (в Android у вас есть выбор между статическим и динамическим, в iOS нет - он всегда статический).
источник
Программы на C ++ строятся в два этапа
Статическая библиотека (.lib) - это просто набор файлов .obj и, следовательно, не полная программа. Он не прошел второй (связующий) этап построения программы. Dll, с другой стороны, похожи на exe и, следовательно, являются законченными программами.
Если вы создаете статическую библиотеку, она еще не связана, и поэтому потребители вашей статической библиотеки должны будут использовать тот же компилятор, который вы использовали (если вы использовали g ++, им придется использовать g ++).
Если вместо этого вы создали dll (и создали ее правильно ), вы создали полную программу, которую могут использовать все потребители, независимо от того, какой компилятор они используют. Однако существует несколько ограничений на экспорт из dll, если требуется кросс-компиляторная совместимость.
источник
consumers of your static library will have to use the same compiler that you used
если статическая библиотека использует библиотеку C ++, например#include <iostream>
.Создание статической библиотеки
создание динамической библиотеки
источник
Статическая библиотека компилируется в клиент. .Lib используется во время компиляции, а содержимое библиотеки становится частью исполняемого файла-потребителя.
Динамическая библиотека загружается во время выполнения и не компилируется в исполняемый файл клиента. Динамические библиотеки более гибкие, так как несколько клиентских исполняемых файлов могут загружать DLL и использовать ее функциональные возможности. Это также сводит к минимуму общий размер и удобство обслуживания вашего клиентского кода.
источник
Вы должны тщательно обдумать изменения во времени, версии, стабильность, совместимость и т. Д.
Если есть два приложения, которые используют общий код, хотите ли вы заставить эти приложения изменяться вместе, если они должны быть совместимы друг с другом? Тогда используйте DLL. Все исполняемые файлы будут использовать один и тот же код.
Или вы хотите изолировать их друг от друга, чтобы вы могли изменить одно и быть уверенным, что не сломали другое. Тогда используйте статическую библиотеку.
DLL ад - это когда вы, вероятно, ДОЛЖНЫ ИСПОЛЬЗОВАТЬ статическую библиотеку, но вместо этого вы использовали dll, и не все exes совместимы с ней.
источник
Статическая библиотека должна быть связана с конечным исполняемым файлом; он становится частью исполняемого файла и следует за ним куда угодно. Динамическая библиотека загружается при каждом выполнении исполняемого файла и остается отдельной от исполняемого файла в виде файла DLL.
Вы должны использовать DLL, если хотите иметь возможность изменять функциональные возможности, предоставляемые библиотекой, без необходимости повторного связывания исполняемого файла (просто замените файл DLL, не заменяя исполняемый файл).
Вы должны использовать статическую библиотеку, когда у вас нет причин использовать динамическую библиотеку.
источник
Статья Ульриха Дреппера « Как писать общие библиотеки » также является хорошим ресурсом, в котором подробно рассказывается о том, как наилучшим образом использовать преимущества общих библиотек, или о том, что он называет «динамическими общими объектами» (DSO). В нем больше внимания уделяется общим библиотекам в двоичном формате ELF , но некоторые обсуждения также подходят для библиотек DLL Windows.
источник
Для отличного обсуждения этой темы прочитайте эту статью от Sun.
Он включает в себя все преимущества, включая возможность вставлять вставные библиотеки. Более подробно о вставке можно найти в этой статье здесь .
источник
На самом деле компромисс, который вы делаете (в большом проекте), заключается в начальном времени загрузки, библиотеки будут связаны тем или иным образом, решение, которое нужно будет сделать, - это то, что ссылка займет достаточно много времени, необходимого компилятору. чтобы укусить пулю и сделать это заранее, или динамический компоновщик может сделать это во время загрузки.
источник
Если ваша библиотека будет разделена между несколькими исполняемыми файлами, часто имеет смысл сделать ее динамической, чтобы уменьшить размер исполняемых файлов. В противном случае, определенно сделайте это статичным.
Есть несколько недостатков использования DLL. Есть дополнительные накладные расходы для загрузки и выгрузки. Существует также дополнительная зависимость. Если вы измените dll, чтобы сделать его несовместимым с вашими executalbes, они перестанут работать. С другой стороны, если вы измените статическую библиотеку, ваши скомпилированные исполняемые файлы, использующие старую версию, не будут затронуты.
источник
Если библиотека статическая, то во время компоновки код связывается с вашим исполняемым файлом. Это делает ваш исполняемый файл больше (чем если бы вы пошли динамический маршрут).
Если библиотека динамическая, то во время компоновки ссылки на требуемые методы встроены в ваш исполняемый файл. Это означает, что вы должны отправить свой исполняемый файл и динамическую библиотеку. Вы также должны подумать, является ли общий доступ к коду в библиотеке безопасным, предпочтительным адресом загрузки среди других вещей.
Если вы можете жить со статической библиотекой, используйте статическую библиотеку.
источник
Мы используем много DLL (> 100) в нашем проекте. Эти библиотеки DLL зависят друг от друга, и поэтому мы выбрали настройку динамического связывания. Однако он имеет следующие недостатки:
Возможно, лучшей настройкой было сделать все статической библиотекой (и, следовательно, у вас есть только один исполняемый файл). Это работает, только если не происходит дублирование кода. Тест, кажется, подтверждает это предположение, но я не смог найти официальную цитату MSDN. Так, например, сделайте 1 exe с:
Код и переменные shared_lib2 должны присутствовать в конечном объединенном исполняемом файле только один раз. Кто-нибудь может поддержать этот вопрос?
источник
Статические библиотеки - это архивы, которые содержат объектный код для библиотеки, когда связаны с приложением, этот код компилируется в исполняемый файл. Общие библиотеки отличаются тем, что они не скомпилированы в исполняемый файл. Вместо этого динамический компоновщик ищет некоторые каталоги в поисках нужных ему библиотек, а затем загружает их в память. Более чем один исполняемый файл может одновременно использовать одну и ту же общую библиотеку, что снижает использование памяти и размер исполняемого файла. Тем не менее, есть еще файлы для распространения с исполняемым файлом. Вы должны убедиться, что библиотека установлена в той системе, где ее может найти компоновщик, статическое связывание устраняет эту проблему, но приводит к увеличению размера исполняемого файла.
источник
Если вы работаете над встроенными проектами или специализированными платформами, статические библиотеки - это единственный путь, а также зачастую они не так сложны для компиляции в ваше приложение. Также наличие проектов и makefile, которые включают все, делает жизнь счастливее.
источник
Я бы дал общее практическое правило: если у вас большая кодовая база, все построено на низкоуровневых библиотеках (например, Utils или Gui Framework), которые вы хотите разделить на более управляемые библиотеки, то сделайте их статическими библиотеками. Динамические библиотеки на самом деле ничего не покупают, и сюрпризов меньше - например, будет только один экземпляр синглетонов.
Если у вас есть библиотека, которая полностью отделена от остальной базы кода (например, сторонней библиотеки), тогда подумайте о том, чтобы сделать ее dll. Если библиотека LGPL, вам может понадобиться использовать DLL в любом случае из-за условий лицензирования.
источник