Динамические библиотеки имеют стоимость времени выполнения из-за перемещений †, поскольку базовый и относительный адрес загрузки библиотеки неизвестен до времени выполнения.То есть вызовы функций и доступ к переменным динамическим библиотекам являются косвенными.По этой причине код для разделяемых библиотек должен быть скомпилирован как независимый от позиции код (флаг -fPIC
в gcc
).
В то время как со статическими библиотеками он может использовать более дешевый программный счетчик относительного доступа даже с адресным пространствомрандомизация, потому что относительное положение этой статической библиотеки (на самом деле объектные файлы) доступно для компоновщика.
Обратите внимание, что вызовы виртуальных функций разрешаются через vtable (который динамический компоновщик может исправлять при загрузке), так чтостоимость вызова виртуальной функции всегда одинакова независимо от того, где находится эта функция.(IIRC, мне может понадобиться перепроверить это утверждение).
См. Как писать общие библиотеки Ульрихом Дреппером для получения полной информации.
Ссылка наСовместно используемые библиотеки проще, потому что они содержат список других общих библиотек, от которых они зависят.
Принимая во внимание, что при связывании со статической библиотекой необходимо также явно связать зависимости этой статической библиотеки (потому что .a
простокуча .o
файлов).
Система сборки должна выполнять дополнительную обработку статических библиотек, чтобы пользователю не приходилось перечислять статические зависимости библиотек каждый раз при его связывании.
КогдаПри связывании со статической библиотекой компоновщик извлекает только те файлы .o
из .a
, которые разрешают любые неразрешенные символы, тогда как во время выполнения загружается вся общая библиотека.Таким образом, если у вас есть глобальный объект в .o
с побочными эффектами конструктора / деструктора, эти побочные эффекты не будут происходить со статической библиотекой, если этот глобальный объект не связан. Необходимо соблюдать особую осторожность, чтобыэтот глобальный объект всегда связан в .
При связывании с общей библиотекой, находящейся в нестандартном месте, наряду с -L<path>
необходимо указать -Wl,-rpath=<path>
для компоновщика во время выполнениячтобы найти там разделяемую библиотеку и / или использовать -Wl, -rpath = $ ORIGIN , если разделяемая библиотека поставляется с исполняемым файлом. Неправильно установить LD_LIBRARY_PATH
.
† Что такое PLT / GOT?