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:
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:
hello.cpp: In function 'int main()'— where the problem is, at function granularity.hello.cpp:5:20— file, line 5, column 20.error: expected ';' before 'return'— what the compiler wanted.- 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¶
- Fix the first error, not all of them. One mistake often produces twenty messages. Rebuild after each fix; usually most of them disappear.
- 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. - Look at the line above. As in Your First Program, the reported location is often one line later than the actual mistake.
- Count braces when a file's error count explodes. A missing
}produces nonsense errors from that point onwards. - Trust the presence of
error:over the wording. Compiler English is awkward; the file and line are not. - 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:
- Read the first error, not the whole output. Then fix it and rebuild.
- 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.
- Look for "required from here". That is the compiler explaining which of your lines triggered the instantiation.
- If you cannot find your own file names in the message at all, the problem is
probably a missing
#includeor 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:
- Does the first error mention a line you recognise? Go there.
- Is the reported line just after the real mistake? Check the line above.
- Are the braces balanced? An editor that highlights matching braces will show a problem instantly.
- Is every name declared before it is used, and spelled identically?
- Is the needed header included?
- If it says
undefined reference, did you compile every.cppfile, and is the function actually defined somewhere? - 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.
- Restate the error in your own words. "The compiler cannot find a function
called
fthat takes twoints" is a question you can answer.
Next: Study Plan · Or begin: Module 1