C++ Error Messages Explained: What They Mean and How to Fix Them
C++ error messages have a well-deserved reputation for being cryptic. The compiler dumps 30 lines of template noise at you when you mistype a variable name. Learning to read these messages — to extract the actual problem from the surrounding noise — is one of the most useful skills you can develop as a C++ programmer.
This guide covers the most common error messages beginners encounter, what they actually mean, and how to fix them.
How to Read C++ Error Messages
Before tackling specific errors, here’s the most important advice: always read the first error first.
Compilers process code sequentially. One mistake early on causes the compiler to lose context, which triggers a cascade of follow-on errors that don’t reflect real bugs. Fix the first error, recompile, and the rest often disappear.
Error messages typically look like this:
main.cpp:10:5: error: 'x' was not declared in this scope
Breaking it down:
main.cpp— the file10— the line number5— the columnerror:— severity (could also bewarning:ornote:)'x' was not declared in this scope— the actual message
Go directly to that line. The problem is there or in the few lines before it.
‘was not declared in this scope’
What it means: You’re using a name (variable, function, type) that the compiler doesn’t know about at that point in the code.
int main() {
cout << "Hello" << endl; // Error: 'cout' was not declared
return 0;
}
Common causes and fixes:
Forgot a #include:
#include <iostream> // Add this
using namespace std;
int main() {
cout << "Hello" << endl; // Works now
}
Typo in the variable name:
int myNumber = 10;
cout << myNubmer << endl; // Typo: 'myNubmer' not declared
Using a variable outside its scope:
if (true) {
int x = 5;
}
cout << x << endl; // Error: x doesn't exist here
Variables declared inside {} only exist inside those braces. Declare x before the if block if you need it after.
‘undefined reference to’
What it means: This is a linker error, not a compiler error. The difference matters. The compiler found a declaration (a promise that something exists) but the linker couldn’t find the actual implementation.
undefined reference to 'MyClass::doSomething()'
Common causes and fixes:
Function declared but not defined:
// You wrote a declaration:
void greet();
int main() {
greet(); // Error: undefined reference
}
// But never wrote the definition (the actual body):
// void greet() { cout << "Hi"; }
Fix: write the implementation.
Forgot to compile a .cpp file
If your project has main.cpp and utils.cpp, you must compile both:
g++ main.cpp utils.cpp -o myprogram
Not just g++ main.cpp.
Missing library flag
Some functions require you to link a library:
g++ main.cpp -o myprogram -lm # Link math library
g++ main.cpp -o myprogram -lpthread # Link thread library
For a deeper look at linker errors, see the dedicated Undefined Reference Linker Errors article.
‘no matching function for call to’
What it means: You called a function, but no version of that function accepts the arguments you provided.
void print(int n) {
cout << n << endl;
}
int main() {
print("hello"); // Error: no matching function for call to 'print(const char*)'
}
Common causes and fixes:
Wrong argument type: Pass an int, not a string: print(42);
Wrong number of arguments:
int add(int a, int b) { return a + b; }
add(1, 2, 3); // Error: too many arguments
Missing #include for the function:
// Error if <algorithm> isn't included
sort(v.begin(), v.end());
Passing const where non-const expected (or vice versa):
void modify(string& s) { s = "changed"; }
modify("literal"); // Error: can't bind temp to non-const ref
Fix: either make the parameter const string& if you don’t need to modify it, or pass a variable instead.
‘expected ’;’ before’
What it means: The parser expected a semicolon and didn’t find one. Usually a missing ; on the previous line.
int x = 5 // Missing semicolon
int y = 10; // Error reported here
The error appears on line 2 even though the bug is on line 1. This is common — always look at the line before the error.
Other causes:
- Mismatched braces causing the parser to lose track of where statements end
- A typo that causes the parser to misinterpret the code structure
’cannot convert’ / ‘invalid conversion from’
What it means: You’re trying to assign or pass a value of a type that the compiler won’t automatically convert.
int n = "hello"; // Error: cannot convert 'const char*' to 'int'
double d = 3.14;
int* p = d; // Error: cannot convert 'double' to 'int*'
Fix: Use the correct type, or an explicit conversion where appropriate:
int n = (int)3.14; // Explicit cast
string s = to_string(42); // Correct way to convert int to string
‘redefinition of’ / ‘redeclared as different kind of symbol’
What it means: You’ve defined something twice with the same name.
int count = 0;
int count = 5; // Error: redefinition of 'count'
Common in larger projects when you have multiple .h files included multiple times. Fix with include guards:
// In myheader.h:
#ifndef MYHEADER_H
#define MYHEADER_H
// ... your declarations ...
#endif
Or with #pragma once (simpler, but non-standard):
#pragma once
// ... your declarations ...
‘control reaches end of non-void function’
What it means: A function that should return a value might not return anything if certain code paths are followed.
int absolute(int n) {
if (n >= 0) return n;
// Warning: what if n < 0? Nothing returned!
}
Fix: handle all paths:
int absolute(int n) {
if (n >= 0) return n;
return -n; // Covers the negative case
}
‘use of uninitialized variable’
What it means: You declared a variable but never gave it a value before reading it. In C++, local variables don’t have default values — they contain whatever garbage was in memory.
int x;
cout << x << endl; // Could print anything
Fix: always initialise your variables:
int x = 0;
Template Error Walls
If you use STL containers or algorithms incorrectly, you’ll sometimes see error messages 50 lines long because templates expand into complex code. The key is finding your code in the error, not the template internals.
Look for lines mentioning your file and line numbers:
main.cpp:15:5: error: no matching function...
That’s the real source. Everything else is the compiler explaining what it tried and failed.
Segmentation Fault (Runtime Error)
This isn’t a compiler error — it happens at runtime. It means your program tried to access memory it doesn’t own.
Common causes:
- Null pointer dereference:
int* p = nullptr; *p = 5; - Array out of bounds:
int arr[3]; arr[10] = 1; - Using freed memory: accessing a pointer after
delete
Fix: check pointer validity before dereferencing, check array bounds, and use tools like Valgrind or AddressSanitizer (-fsanitize=address compiler flag) to find memory errors.
Quick Error Reference
| Error message | Likely cause |
|---|---|
was not declared in this scope | Missing #include, typo, or wrong scope |
undefined reference to | Linker can’t find implementation |
no matching function for call to | Wrong argument types/count |
expected ';' before | Missing semicolon on previous line |
cannot convert | Type mismatch |
redefinition of | Defined twice, missing include guards |
control reaches end of non-void function | Missing return in some code path |
use of uninitialized variable | Variable used before assignment |
| Segmentation fault | Bad memory access at runtime |
Related Articles
- Debugging C++ with GDB — step through your code to find runtime bugs
- Undefined Reference Linker Errors in C++ — a deeper dive into linker errors
- C++ Functions Tutorial — understanding function declarations vs definitions
- C++ Pointers — understanding pointers to prevent segfaults
- Exception Handling in C++ — handling runtime errors gracefully
Take Your C++ Further
If you’re looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you’re a complete beginner or looking to solidify your understanding. Just $19.