Skip to content

Reading Compiler Errors

Beginners lose more time to unreadable error output than to the C++ language itself. This page teaches you to read that output the way an experienced programmer does: quickly, calmly, and in the right order.

Wording differs; structure does not

Message text and column numbers vary between GCC, Clang and MSVC and across versions of each. Everything below is about structure — the pattern to look for — which is stable everywhere.


The three kinds of "the program won't work"

Knowing which kind you have tells you where to look.

Kind When it happens Who reports it Example
Compile error While building The compiler expected ';' before 'return'
Link error At the very end of building The linker undefined reference to 'Book::Book()'
Runtime error When the program runs Nothing, or the OS Segmentation fault

A compile error tells you what is wrong with how you wrote it. A link error tells you something you declared was never defined, or that you forgot to include a file in the command. A runtime error — a crash or wrong answer — is the hardest, and Modules 10, 11 and 13 are largely about preventing it. As a rule: if it compiles and then misbehaves, the compiler is not the problem.


Anatomy of a message

Take this program:

#include <iostream>

int main() {
    int count = 0;
    std::cout << count
    return 0;
}

The missing ; produces something like:

hello.cpp: In function 'int main()':
hello.cpp:5:20: error: expected ';' before 'return'
    5 |     std::cout << count
      |                    ^

Read it in four parts:

  1. hello.cpp: In function 'int main()' — where the problem is, at function granularity.
  2. hello.cpp:5:20 — file, line 5, column 20.
  3. error: expected ';' before 'return' — what the compiler wanted.
  4. The quoted source line and the ^ caret — the exact spot. Recent GCC and Clang versions print this automatically; with older ones you may only get the line number.

Six habits that make this fast

  1. Fix the first error, not all of them. One mistake often produces twenty messages. Rebuild after each fix; usually most of them disappear.
  2. Read from the bottom of the first block. Compilers often emit a note: line after the error giving the real explanation ("did you mean #include <iostream>?"). The note is frequently more useful than the error.
  3. Look at the line above. As in Your First Program, the reported location is often one line later than the actual mistake.
  4. Count braces when a file's error count explodes. A missing } produces nonsense errors from that point onwards.
  5. Trust the presence of error: over the wording. Compiler English is awkward; the file and line are not.
  6. Do not wrestle long template errors. They are the worst case. Work outside-in: read the first and last lines of the message, and see template errors below.

Catalogue of errors you will actually meet

Grouped by cause. Line numbers and wording will differ in your compiler.

Syntax and punctuation

Message (abbreviated) Cause Fix
error: expected ';' before '}' Missing semicolon on the previous statement Look at the line above the reported one
error: expected '}' at end of input Unbalanced braces — one { too many Count braces from the innermost function outwards
error: expected initializer before 'cout' A missing #include or a stray character earlier Check the lines above and the includes
error: expected primary-expression before ';' An incomplete expression, often a forgotten operand Re-read the whole statement
error: expected declaration before '}' A stray extra } Delete it, or reinstate the block it should have closed

Names, scope, and typos

Message (abbreviated) Cause Fix
error: 'x' was not declared in this scope The name does not exist here: a typo, a missing declaration, or a variable declared inside another block Check spelling; check the name is declared before this line; check the braces
error: 'cout' was not declared in this scope Missing #include <iostream> or missing std:: Add the include, and write std::cout
error: 'cour' is not a member of 'std' Typo in a standard-library name Compare against the correct spelling
error: 'foo' does not name a type Usually a missing ; after the previous class or struct, or a typo in a type name Check the end of the previous declaration
error: 'class Book' has no member named 'titl' Typo in a member name, or the member is private Check the spelling and the access level
error: redefinition of 'x' The same variable or function defined twice Remove one, or move it out of the header
error: 'x' redeclared as different kind of symbol Two things with the same name, e.g. a function and a variable Rename one

Types and conversions

The compiler is refusing to silently reinterpret your data. This is a feature.

Message (abbreviated) Cause Fix
error: invalid conversion from 'int' to 'int*' Passing a value where a pointer is required Take the address with &, or change the parameter type
error: cannot convert 'std::string' to 'const char*' Mixing std::string with a C-style API Use .c_str() deliberately, or a std::string overload
error: no matching function for call to 'f(int, int)' No overload matches these argument types or count Read the candidate: notes — they list the signatures the compiler did find
error: too few/many arguments to function Wrong number of arguments Match the declaration
error: assigning to 'const int' from 'int' Writing to something declared const Either it should not be const, or you are modifying the wrong variable
error: passing 'const Book' as 'this' argument discards qualifiers Calling a non-const member function on a const object This is const-correctness doing its job: mark the member function const if it does not modify the object. See Module 4
error: use of deleted function You used a copy or move that was explicitly = deleted (or is unavailable) Pass by reference, or redesign ownership. See Module 10

Classes, inheritance and virtual functions

Message (abbreviated) Cause Fix
error: cannot declare variable 'b' to be of abstract type 'Shape' Instantiating a class with a pure virtual function This is intentional — instantiate a concrete derived class instead. See Module 8
error: 'void Shape::draw()' marked 'override', but does not override The base signature does not match exactly — often a wrong parameter list or a missing const Make the signature identical to the base's
error: 'override' is not allowed here / virtual outside a class You wrote a class member outside a class body Move the declaration inside the class
error: no matching function for call to 'Derived::Derived()' The base class has no default constructor, and the derived constructor does not call one explicitly Add the base initialisation to the member initialiser list. See Module 6
error: 'Base' is an inaccessible base of 'Derived' The inheritance was declared private or protected where public was meant Write public Base

Linker errors — after everything compiled

These look different and mean something different: your syntax was fine, but a piece is missing or duplicated.

Message (abbreviated) Cause Fix
undefined reference to 'Book::Book()' The function was declared but never defined, or its .cpp file was not included in the build command Add the definition, and list every source file: g++ -std=c++17 main.cpp book.cpp -o app
undefined reference to 'std::...' on a C library call Usually a missing library on the command line Add the required library (e.g. -lm, -lpthread)
multiple definition of 'helper()' A function defined (not just declared) in a header included twice — the One Definition Rule Leave the declaration in the header and move the definition to one .cpp file. See Module 16
ld returned 1 exit status The generic "the linker failed" ending — always preceded by the real cause Read the lines above it

Warnings — the ones you should not ignore

With -Wall -Wextra, warnings are the compiler telling you it suspects a bug. The course treats them as errors to fix, because that habit prevents a large class of runtime bugs.

Warning (abbreviated) Cause Fix
warning: unused variable 'x' Declared and never used — often a leftover or a typo Remove it, or use it
warning: control reaches end of non-void function A path through the function returns nothing Add a return, or restructure the branches
warning: comparison of integer expressions of different signedness Comparing int with unsigned/size_t, which can behave surprisingly for negative values Enable -Wsign-compare reasoning: prefer std::size_t for sizes and indices
warning: variable 'x' set but not used Assigned, never read — often you meant to use it Check the logic
warning: 'x' may be used uninitialized A variable is read before it is given a value Initialise it at declaration
warning: no return statement in function returning non-void Same family as above Add the return

Turn warnings into errors when you are ready

g++ -std=c++17 -Wall -Wextra -Werror ... makes every warning fail the build. It is an excellent habit once your code compiles at all — and it is what the course's own quality checks do.


Template errors: the hard case

From Module 12 onwards, a single mistake can produce hundreds of lines. Do this:

  1. Read the first error, not the whole output. Then fix it and rebuild.
  2. Find the innermost "note:" chain. Errors are reported inside-out: the real problem (your code) is usually at the bottom of the chain, while the top shows the library function that received your bad type.
  3. Look for "required from here". That is the compiler explaining which of your lines triggered the instantiation.
  4. If you cannot find your own file names in the message at all, the problem is probably a missing #include or a wrong type passed in from elsewhere.

Long messages are not a sign that C++ is broken. They are the compiler showing the entire path your code took.


A method to fall back on

When nothing makes sense, work through this list in order — it resolves most beginner errors:

  1. Does the first error mention a line you recognise? Go there.
  2. Is the reported line just after the real mistake? Check the line above.
  3. Are the braces balanced? An editor that highlights matching braces will show a problem instantly.
  4. Is every name declared before it is used, and spelled identically?
  5. Is the needed header included?
  6. If it says undefined reference, did you compile every .cpp file, and is the function actually defined somewhere?
  7. Reduce the problem: comment out code until it compiles, then put it back a piece at a time. The line that breaks the build is the line to examine.
  8. Restate the error in your own words. "The compiler cannot find a function called f that takes two ints" is a question you can answer.

Next: Study Plan · Or begin: Module 1