C++ Linker Error (undefined reference) Fix
In this tutorial, you'll learn about C++ Linker Error (undefined reference) Fix. We cover key concepts, practical examples, and best practices.
The Problem
Your C++ program compiles but fails to link:
$ g++ -o myprogram main.cpp
/usr/bin/ld: /tmp/ccXYZ123.o: in function `main':
main.cpp:(.text+0x14): undefined reference to `calculateSum(int, int)'
collect2: error: ld returned 1 exit status
The compiler compiled each source file successfully, but the linker cannot find the definition of a function, variable, or class method that was declared but never defined, or defined in a file that was not linked.
Quick Fix
Step 1: Check that the definition exists
WRONG -- function declared but never defined:
// math_utils.h
int calculateSum(int a, int b); // declaration only
// main.cpp
#include "math_utils.h"
int main() {
return calculateSum(2, 3); // linker cannot find the definition
}
RIGHT -- add the definition:
// math_utils.cpp
int calculateSum(int a, int b) {
return a + b;
}
Then link both files:
g++ -o myprogram main.cpp math_utils.cpp
Step 2: Include all object files in the link command
WRONG -- missing an object file:
g++ -c main.cpp # produces main.o
g++ -c math_utils.cpp # produces math_utils.o
g++ -o myprogram main.o # forgot to include math_utils.o
RIGHT -- include all object files:
g++ -o myprogram main.o math_utils.o
Step 3: Fix library linking order
WRONG -- library before the object file that needs it:
g++ -o myprogram -lmylib main.o # linker cannot resolve symbols from main.o
RIGHT -- object files before libraries:
g++ -o myprogram main.o -lmylib # main.o references mylib symbols
For static libraries, order matters: list libraries after all object files:
g++ -o myprogram main.o -L. -lmylib -lotherlib
Step 4: Check for C++ name mangling issues
WRONG -- C function compiled with C++ compiler but declared without extern "C":
// c_library.h (compiled by C compiler)
int c_function(int x); // C name: c_function
// main.cpp (compiled by C++ compiler)
#include "c_library.h" // C++ looks for _Z11c_functioni (mangled name)
int main() {
return c_function(5); // linker error
}
RIGHT -- wrap in extern "C":
extern "C" {
#include "c_library.h"
}
int main() {
return c_function(5); // looks for C name: c_function
}
Step 5: Check for mismatched function signatures
WRONG -- declaration and definition have different signatures:
// header.h
void process(int x, double y);
// implementation.cpp
void process(double y, int x) { // parameter order swapped!
// ...
}
RIGHT -- keep declarations in sync:
// header.h
void process(int x, double y);
// implementation.cpp
void process(int x, double y) {
// ...
}
Step 6: Check template definition visibility
WRONG -- template declared in header but defined in .cpp:
// utils.h
template <typename T>
T maxValue(T a, T b); // declaration only
// utils.cpp
template <typename T>
T maxValue(T a, T b) { return (a > b) ? a : b; }
// Definition is only visible in this translation unit
RIGHT -- define templates in the header, or use explicit instantiation:
// utils.h
template <typename T>
T maxValue(T a, T b) {
return (a > b) ? a : b;
}
// utils.cpp
template int maxValue<int>(int, int); // explicit instantiation
Use DodaTech's Dependency Inspector to trace symbol references, detect missing libraries, and resolve circular dependencies in your build graph.
Prevention
- Always compile and link all source files together in the build command.
- Use a build system (CMake, Make, Meson) to manage file dependencies.
- Place libraries after object files on the linker command line.
- Use
extern "C"for all C library headers included in C++ code. - Define templates in headers, not in .cpp files.
Common Mistakes with linker error
- Mixing let bindings with <- bindings in do notation, producing type errors
- Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
These mistakes appear frequently in real-world CPP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro