Это зависит.
Если библиотека является общим объектом или DLL, то все содержимое библиотеки загружается, но во время выполнения. Стоимость дополнительной памяти (надеюсь) компенсируется за счет совместного использования библиотеки (в действительности кодовых страниц) между всеми процессами в памяти, которые используют эту библиотеку. Это большая победа для чего-то вроде libc
.so, меньше для myreallyobscurelibrary.so
. Но вы, вероятно, не спрашиваете об общих объектах, действительно.
Статические библиотеки - это просто набор отдельных объектных файлов, каждый из которых является результатом отдельной компиляции (или сборки) и, возможно, даже не написан на том же исходном языке. Каждый объектный файл имеет количество экспортируемых символов и почти всегда количество импортируемых символов.
Задача компоновщика - создать готовый исполняемый файл, в котором нет оставшихся неопределенных импортированных символов. (Я лгу, конечно, если динамическое связывание разрешено, но потерпите меня.) Для этого он начинается с модулей, названных явно в командной строке ссылки (и, возможно, неявно в его конфигурации) и предполагает, что любой модуль named явно должен быть частью готового исполняемого файла. Затем он пытается найти определения для всех неопределенных символов.
Обычно именованные объектные модули ожидают получить символы из некоторой библиотеки, такой как libc.a
.
В вашем примере у вас есть единственный модуль, который вызывает функцию a()
, в результате чего компоновщик ищет модуль, который экспортирует a()
.
Вы говорите, что библиотека с именем A (в Unix, вероятно, libA.a
) предлагает a()
и b()
, но вы не указываете как. Вы подразумевали, что a()
и b()
не звонят друг другу, как я предполагаю.
Если libA.a
был построен из a.o
и b.o
, где каждая определяет соответствующую отдельную функцию, тогда компоновщик будет включать a.o
и игнорировать b.o
.
Однако, если libA.a
включает ab.o
, который определяет и a()
, и b()
, то он будет включать ab.o
в ссылку, удовлетворяя потребность в a()
и включая неиспользуемую функцию b()
,
Как уже упоминалось, существуют линкеры, которые способны разделять отдельные функции из модулей и включать только те, которые фактически используются. Во многих случаях это безопасно. Но обычно безопаснее предположить, что ваш компоновщик не сделает этого, если у вас нет конкретной документации.
Еще кое-что, о чем следует знать, - это то, что большинство компоновщиков делают как можно меньше проходов по файлам и библиотекам, названным в командной строке, и создают свою таблицу символов на ходу. На практике это означает, что рекомендуется всегда указывать библиотеки после всех объектных модулей в командной строке ссылки.