Что происходит с C-файлом от написания до получения исполняемого файла
Что проверяют
Знаете ли вы этапы сборки и умеете ли по тексту ошибки понять, на каком из них сломалось. Для тестировщика это про адресацию дефекта и про воспроизводимость: одна и та же программа ведёт себя по-разному в отладочной и релизной сборке.
Как отвечать
Путь исходника до запуска проходит четыре шага.
- препроцессор подставляет содержимое
#include, раскрывает макросы, вырезает ветки#ifdefи убирает комментарии. На выходе всё ещё текст на C; - компилятор разбирает синтаксис, проверяет семантику, оптимизирует и выдаёт текст на ассемблере под конкретную архитектуру;
- ассемблер переводит этот текст в машинный код и складывает объектный файл с таблицей символов;
- компоновщик сшивает объектные файлы и библиотеки, разрешает ссылки на внешние функции, добавляет стартовый код и выдаёт исполняемый файл.
Пятый шаг происходит уже при запуске: загрузчик операционной системы подтягивает динамические библиотеки, поэтому собранный бинарник может не стартовать на другой машине.
Что из этого пригодится в работе: ошибки препроцессора и компилятора указывают на файл и строку, сообщение про неразрешённую ссылку это уже компоновка, а падение сразу при старте обычно про отсутствующую или несовместимую библиотеку. Отладочная сборка несёт символы и почти не оптимизирована, релизная быстрее и без символов, и часть дефектов воспроизводится только в одной из них.
Где спотыкаются
Путают порядок двух средних шагов и говорят, что компилятор сразу выдаёт объектный файл, а ассемблер потом переводит машинный код в ассемблерный. Направление обратное: сначала ассемблерный текст, потом машинный код.
Считают компоновку формальностью. Именно там всплывают дубликаты символов, библиотека не той разрядности, неверный порядок библиотек в команде сборки. Такие сообщения не привязаны к строке исходника, и их часто ошибочно заводят как ошибку компиляции.
Не отделяют сборку от среды запуска. Программа берёт версии библиотек с той машины, где запущена, поэтому «у меня не воспроизводится» нередко означает разное окружение, а не разный код. В отчёт стоит класть и версию сборки, и состав окружения.