Ответ
Линкер — это программа, которая принимает на вход один или несколько объектных файлов (.o, .obj), полученных от компилятора, и библиотеки, а на выходе создаёт единый исполняемый файл или библиотеку. Его ключевая задача — разрешение внешних ссылок.
Конкретные функции линкера:
- Связывание (Resolution): Объектный файл содержит «ссылки» на имена функций и глобальных переменных, определённых в других файлах или библиотеках (например,
coutиз стандартной библиотеки). Линкер находит эти определения и подставляет правильные адреса. - Объединение секций: Код из разных
.oфайлов собирается в секцию.text, данные — в.dataили.bssи т.д. - Распределение адресов: Назначает окончательные виртуальные адреса для всех частей программы.
Типичные ошибки линкера:
undefined reference to 'symbol': Линкер не нашёл определение для объявленного символа. Причина: забыли подключить объектный файл или библиотеку, опечатка в имени.multiple definition of 'symbol': Обнаружено более одного определения одного символа. Частая причина — определение функции в заголовочном файле безinlineилиstatic, который включили в несколько.cpp-файлов.
Пример:
// math_utils.h
#pragma once
extern int global_counter; // Объявление глобальной переменной
int add(int a, int b); // Объявление функции
// math_utils.cpp
#include "math_utils.h"
int global_counter = 0; // Определение глобальной переменной
int add(int a, int b) { // Определение функции
return a + b;
}
// main.cpp
#include "math_utils.h"
#include <iostream>
int main() {
global_counter++;
std::cout << add(5, 3); // Вызов функции, определённой в другом файле
return 0;
}
Линкер соберёт main.o и math_utils.o, связав вызов add и обращение к global_counter с их определениями.