Как читать ошибки компилятора C++: разбираем шаг за шагом
Компилятор C++ выдаёт полотно текста на одну забытую точку с запятой. Учимся находить первую настоящую ошибку и понимать, что от вас хочет g++ или clang.

Вы написали первую программу на C++, нажали компиляцию — и получили тридцать строк текста, где слово error тонет среди note, required from here и раскрытых имён шаблонов длиной в абзац. К концу этого разбора вы научитесь находить в этом полотне первую настоящую ошибку, читать её структуру и понимать пять сообщений, на которые новичок натыкается в первую неделю. Времени уйдёт минут двадцать, если разбирать примеры вместе с компилятором.
Всё ниже проверялось на g++ 13 и clang 17 со стандартом C++17 (флаг -std=c++17). Формулировки ошибок между версиями чуть отличаются, но структура одна.
Что нужно до начала
Чтобы повторять примеры, у вас должно быть установлено одно из двух:
- g++ — проверьте командой
g++ --version, должна вывестись строка с номером версии; - clang++ — проверьте
clang++ --version.
Если команда не найдена, на Linux ставится через sudo apt install g++, на macOS через xcode-select --install, на Windows проще всего взять MSYS2 или собрать в онлайн-компиляторе вроде Compiler Explorer. Дальше в командах используется g++; для clang замените имя, флаги те же.
Как устроена строка ошибки
Каждое сообщение компилятора начинается одинаково. Возьмём типичную строку:
main.cpp:5:14: error: 'y' was not declared in this scopeЧитается слева направо:
main.cpp— файл, где споткнулся компилятор;5— номер строки;14— номер столбца (позиция символа в строке);error— уровень: бывает ещёwarning(предупреждение, компиляция продолжится) иnote(уточнение к предыдущей ошибке, не самостоятельная проблема);- дальше — сам текст.
Под строкой g++ и clang показывают саму проблемную строку кода и стрелку ^, которая указывает на столбец. Это самый быстрый способ найти место: не считайте символы вручную, смотрите на стрелку.
Главное правило: читайте первую ошибку
Компилятор не останавливается на первой проблеме — он пытается разобрать код дальше и часто спотыкается о последствия исходной ошибки. Одна забытая скобка может породить пять сообщений. Девяносто процентов времени чинить нужно самое верхнее error, а потом перекомпилировать заново.
Первая ошибка настоящая, остальные — эхо. Исправили верхнюю строку — запускайте компиляцию снова, не пытаясь чинить всё полотно сразу.
Пять сообщений, которые вы увидите первыми
1. Забытая точка с запятой
Код:
#include <iostream>
int main() {
int count = 5 // забыли ; здесь
std::cout << count;
return 0;
}g++ 13 скажет:
main.cpp:5:5: error: expected ';' before 'std'Обратите внимание: ошибка указывает на строку 5, где стоит std::cout, хотя точку с запятой забыли строкой выше. Так и работает expected ';' before X — компилятор дочитал до X и понял, что предыдущее выражение не завершено. Ищите пропуск в конце предыдущей строки.
2. Необъявленное имя
main.cpp:5:18: error: 'cout' was not declared in this scopeДве частые причины. Либо забыли #include <iostream>, либо написали cout без std::. Формулировка was not declared in this scope означает буквально: компилятор дошёл до имени, но нигде выше его не встречал. Проверяйте по порядку: подключён ли нужный заголовок, не опечатались ли в имени, не забыли ли префикс пространства имён.
3. Несоответствие типов при вызове
#include <string>
void greet(const std::string& name);
int main() {
greet(42); // передаём число туда, где ждут строку
}clang 17 выдаст что-то вроде:
main.cpp:6:5: error: no matching function for call to 'greet'
main.cpp:3:6: note: candidate function not viable: no known conversion from 'int' to 'const std::string &' for 1st argumentКлючевое здесь — строка note. Само error говорит только «не нашёл подходящую функцию», а причину — no known conversion from 'int' to ... — сообщает note. При перегрузках функций именно в note скрывается ответ, почему каждый кандидат не подошёл.
4. Ошибка компоновщика
Это не ошибка компилятора в привычном смысле — код синтаксически верен, но на этапе связывания не нашлась реализация функции:
undefined reference to `foo()'Отличается от предыдущих: нет номера строки и слова error: в начале, зато есть слова reference и ld (это линкер). Причины: объявили функцию, но не написали тело; забыли добавить .cpp файл в команду компиляции; не слинковали библиотеку. Компиляция по файлам прошла, а собрать программу целиком не вышло.
5. Полотно из шаблонов
Самое пугающее для новичка — ошибка внутри std::vector, std::map или другого шаблонного типа. Она разворачивается на десятки строк с раскрытыми именами вроде std::__cxx11::basic_string<char, std::char_traits<char>...>. Не читайте это целиком. Ищите две вещи: первое error сверху и строку required from here — она указывает на место в вашем коде, откуда началась цепочка. Ошибка почти всегда там, а не в недрах стандартной библиотеки.
Быстрый разбор по типу сообщения
| Текст в ошибке | Что обычно значит | Куда смотреть |
|---|---|---|
expected ';' before | Не завершено выражение | Конец предыдущей строки |
was not declared in this scope | Имя не найдено | Include, опечатка, std:: |
no matching function for call | Не тот тип аргумента | Строку note ниже |
undefined reference to | Нет реализации функции | Тело функции, состав команды сборки |
expected '}' at end of input | Не закрыта скобка блока | Баланс фигурных скобок в файле |
Если ошибок много и глаза разбегаются
Несколько флагов делают вывод компилятора терпимее:
-fmax-errors=1(g++) или-ferror-limit=1(clang) — показать только первую ошибку и остановиться. Отучает от паники при виде полотна;-Wall— включить основные предупреждения. Многие будущие баги компилятор поймает какwarningещё до того, как они станут ошибкой в рантайме;- у clang вывод по умолчанию цветной и часто читается легче, чем у g++ — если сообщение непонятно, скомпилируйте тот же файл через
clang++ради второй формулировки.
Пример команды с ограничением на одну ошибку:
g++ -std=c++17 -Wall -fmax-errors=1 main.cpp -o main
Что делать дальше
Возьмите свою рабочую программу и намеренно сломайте её пятью способами из этой статьи по очереди: уберите точку с запятой, сотрите #include, передайте не тот тип. Прочитайте каждое сообщение и убедитесь, что понимаете, куда указывает стрелка. Через несколько таких прогонов вы начнёте узнавать формулировки с первого взгляда.
Следующий шаг — научиться читать предупреждения -Wall и -Wextra: это ошибки, которые компилятор пока прощает, но которые ломают программу уже во время выполнения. Именно там прячутся неинициализированные переменные и сравнения знакового со беззнаковым.
Контент-конвейер: Из одной идеи — текст, изображение, озвучка и ролик. Один заказ вместо четырёх.
Спросить за 60 ₽Источники: GCC Diagnostic Options (официальная документация GCC), Clang Compiler User's Manual — Diagnostics
Частые вопросы
У меня другая версия компилятора, формулировки не совпадают дословно. Это нормально?
Компилятор показывает десять ошибок. С какой начинать?
Ошибка указывает на строку, где всё выглядит правильно. Почему?
Чем warning отличается от error?
Я всё исправил, а undefined reference остаётся. Что не так?
Ошибка внутри std::vector или std::map разворачивается на 40 строк. Как её вообще читать?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.