Ответ 1
Это, вероятно, вас заинтересовало бы, но вот короткая версия:
Когда вы собираете .cpp
, .c
или любые другие файлы, каждая единица перевода (т.е. каждый файл) генерирует объектный файл. При создании окончательного исполняемого файла вы объединяете все объектные файлы в один бинарный файл. Для статических библиотек вы скомпилируете статический архив (.a
или .lib
) вместе со всеми объектными файлами в самом двоичном файле. Для связывания с динамическими общими объектами (.so
или .dll
) двоичный файл создается с вызовами глобальной таблицы смещения, и вы сообщаете компоновщику, что вы хотите связать с общим объектом, а загрузчик операционной системы создает правильное изображение при запуске программы.
Общее объяснение терминов, используемых для связывания библиотек в С++
Начиная с...
перевод. Здесь код высокого уровня (в C, Fortran или любой другой) преобразуется в код сборки посредством единицы перевода. Таким образом, каждый .cpp
файл внутренне переводится в сборку для конкретной архитектуры.
собрать. Создает объектные файлы из сгенерированной сборки. Объектные файлы - это почти машинный код, но у них много "нерешенных внешних", которые вы можете рассматривать как указатели на фактические определения функций.
привязка. Это занимает все ваши объектные файлы и помещает их в последовательный двоичный файл, будь то динамический общий объект или исполняемый файл. Вам нужно сообщить компоновщику, где он должен найти все эти нерешенные внешние элементы с предыдущего этапа, или они будут отображаться здесь как ошибки.
Теперь двоичный файл находится на диске, который ждет, пока...
загрузчик. Операционная система загружает двоичный диск с диска, который содержит всю информацию, необходимую для создания образа программы. Хотя детали чрезвычайно специфичны для платформы, загрузчику обычно поручено находить все ссылки на совместно используемую библиотеку, созданные компоновщиком, загружая их (рекурсивно, поскольку каждый DSO может иметь свои собственные зависимости) и помещать их в пространство памяти программы.