Почему статические и динамически подключаемые библиотеки отличаются? - PullRequest
28 голосов
/ 31 мая 2011

Если они оба содержат скомпилированный код, почему мы не можем загрузить «статические» файлы во время выполнения и почему мы не можем связываться с динамическими библиотеками во время компиляции?Почему необходимо, чтобы отдельные форматы содержали «автономный» код?Что нужно хранить в любом из них, которое гарантирует разницу?

Ответы [ 6 ]

22 голосов
/ 31 мая 2011

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

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

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

Подводя итог:

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

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

6 голосов
/ 31 мая 2011

Код в объектном файле не связан.Он содержит неявные ссылки на внешние функции, которые еще не были разрешены.

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

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

5 голосов
/ 31 мая 2011

Примечание: следующий ответ не не зависит от платформы, но специфичен для систем на базе ELF и некоторых других подобных. Кто-то другой может заполнить данные для других систем.

Что такое статическая библиотека?

Статическая библиотека - это коллекция *.o файлов в архиве. Каждый файл может содержать ссылки на неопределенные символы, которые должны быть разрешены компоновщиком, например, ваша библиотека может иметь ссылку на printf. Библиотека не предоставляет никаких указаний о том, где будет найден printf, ожидается, что компоновщик найдет его в одной из других библиотек, в которых его просят связать.

Предположим, ваша библиотека содержит следующий код:

read_png.o
write_png.o
read_jpg.o
write_jpg.o
resize_image.o
handle_error.o

Если приложение использует только read_png и write_png, то другие части кода не будут загружены в исполняемый файл (кроме handle_error, который вызывается из read_png и write_png).

Мы не можем загрузить статическую библиотеку во время выполнения, потому что:

  • Компоновщик не знает, где найти внешние объекты, например, printf.

  • Это будет медленно. Динамические библиотеки оптимизированы для быстрой загрузки.

  • Статические библиотеки не имеют понятия пространств имен. Я не могу определить свой собственный handle_error, потому что это будет противоречить определению библиотеки.

Что такое динамическая библиотека?

Динамическая библиотека в системах ELF - это объект того же типа, что и исполняемый файл. Он также экспортирует больше символов, исполняемый файл требуется только для экспорта _start. Динамические библиотеки оптимизированы, поэтому все это может быть отображено непосредственно в память.

Если у вас есть вызов printf в вашей динамической библиотеке, существуют некоторые дополнительные требования, помимо требований для статических библиотек:

  • Вы должны указать, какая библиотека имеет printf.

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

Мы не хотим использовать динамические библиотеки для статического связывания, потому что:

  • Мы не можем связать только часть динамической библиотеки. Даже если наш исполняемый файл никогда не вызывает read_jpg, он включается, потому что динамические библиотеки все или ничего.

  • Дополнительные затраты на вызовы функций расточительны, даже если они небольшие.

Резюме

Компиляция выглядит примерно так:

Source  ==compile==>  Object  ==link==>  Executable / Shared Library

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

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

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

3 голосов
/ 31 мая 2011

Нет фундаментальной причины, по которой вы не могли бы использовать файлы статической библиотеки (.a) в качестве динамических библиотек, загружая и связывая их во время запуска программы или даже динамически во время выполнения. Однако они не были специально скомпилированы и подготовлены для запуска сопоставления памяти по произвольному адресу (даже выравнивание не обязательно правильное!), Поэтому код загрузчика должен был бы выделять память, считывать необходимые объекты из файлов .a в эту память, и выполнить основные изменения на нем. И, конечно же, ничто из этой памяти не будет общим. Таким образом, это, вероятно, очень плохая идея ...

1 голос
/ 01 июня 2011

Статическая библиотека == tarball , тогда как динамическое == непрерывное изображение частично связано

Статическая библиотека - это просто архив 1 из .o or .obj` файлов. Когда исполняемый файл связан, ссылочные модули (и те, на которые они ссылаются, а затем те, на которые они ссылаются, а затем ... и т. Д.) Копируются из статической библиотеки и добавляются в конец основной программы. Все это заносится в память как единый «объект» ОС.

Динамическая библиотека просто берет все элементы статической библиотеки, связывает их вместе (разрешает внутренние связи) и затем отображает все это в памяти. (Пейджинг по требованию может сделать частичное присутствие в памяти достижимым.) При запуске динамических программ необходимо определенное беспокойство, чтобы подключить основную программу (которая будет «статически» связана в своих собственных модулях) с библиотекой, которая является общей. общесистемный. Иногда эта игра задерживается для каждого элемента связи, пока не будет сделан данный вызов. В очень широком, чрезмерно концептуальном цикле можно было бы классифицировать статическое связывание как стремительная загрузка и динамическое как отложенная загрузка .

Есть плюсы и минусы со статическими библиотеками.

Нет DLL ад (он же ад зависимости )
Значительно меньший объем памяти для небольших смесей процессов во время выполнения
- Значительно больший объем памяти для больших комбинаций процессов во время выполнения разрозненных программ
- Невозможно разделить память библиотечного кода между процессами, кроме случаев, когда они запускают одну и ту же программу
- Большой набор программ (например, следы Linux / Windows / Mac) занимает много места, так как printf и др. дублируются многократно в каждом изображении
- Трудно, если не невозможно, исправлять ошибки безопасности, возникающие в библиотеках
- Трудно, если не невозможно, обновить библиотеку в одиночку
Трудно, если не невозможно, обновить одну библиотеку и сломать вашу программу


1. На самом деле они не в формате tar (1) , но это связано.

0 голосов
/ 09 января 2015

Разница:

  • Статические библиотеки и скомпилированные и связанные
  • Динамические библиотеки связаны

Ссылки

...