Skip to content

C++ Linker Error (undefined reference) Fix

DodaTech Updated 2026-06-24 4 min read

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

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

  1. Mixing let bindings with <- bindings in do notation, producing type errors
  2. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
  3. 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

### What is the difference between a compile error and a linker error?

A compile error occurs when the compiler cannot understand the syntax or types in your code. A linker error occurs after compilation when the linker cannot find the definition of a symbol that was declared somewhere in the code.

How do I find which library provides a missing symbol?

Use nm -C or objdump -T to list symbols in a library: nm -C /usr/lib/libmylib.a | grep calculateSum. Then add that library to your link command with -lmylib.

Template definitions must be visible at the point of instantiation. Move the template implementation from the .cpp file to the header file, or add explicit instantiation declarations in the .cpp file.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro