Menu
How the C++ Linker Works

How the C++ Linker Works

How the C++ Linker Works - ▶️YouTube


Key Concepts

1. Compilation vs. Linking

  • Compilation: Converts .cpp files to .obj files (machine code).
    • Shortcut: Ctrl + F7 (Visual Studio) compiles without linking.
    • Errors: Syntax issues (e.g., missing semicolons, type mismatches).
  • Linking: Combines .obj files into an executable, resolving symbols (functions/variables).
    • Shortcut: F5 (VS) compiles + links + runs.
    • Errors: Missing/multiple definitions (e.g., LNK2019, LNK1169).

2. Entry Point Requirement

Every .exe must have an entry point (default: main()).

  • Custom Entry Point: Configured via linker settings (e.g., Project Properties → Linker → Advanced → Entry Point).
  • Error:
    error LNK1561: entry point must be defined  
    
  • Example:
    // Main.cpp (NO main() function)  
    #include <iostream>  
    void Log(const char* message) { /*...*/ }  // No entry point!  
    

3. Common Linker Errors

A. Unresolved External Symbol (LNK2019)

Cause: Function/variable declared but not defined.

  • Example:
    // Main.cpp  
    void Log(const char* message); // Declaration only  
      
    int main() {  
        Log("Hello"); // Linker error: No definition found!  
    }  
    
    error LNK2019: unresolved external symbol "void Log(char const*)"  
    

    Fix: Provide a definition in one .cpp file.


B. Multiple Definitions (LNK1169)

Cause: Same symbol defined in multiple files.

  • Example:
    // Log.h  
    #pragma once  
    void Log(const char* message) { /*...*/ }  // Definition in header!  
    
    // Main.cpp  
    #include "Log.h"  // Duplicate definition when included in multiple files  
    
    error LNK2005: "void Log(char const*)" already defined in Log.obj  
    

    Fix:

    1. Declare in header, define in one .cpp:
       // Log.h  
       void Log(const char* message);  // Declaration only  
      
       // Log.cpp  
       #include "Log.h"  
       void Log(const char* message) { /*...*/ }  // Single definition  
      
    2. Use inline (for small functions):
       // Log.h  
       inline void Log(const char* message) { /*...*/ }  // No duplication  
      
    3. Use static (limits visibility to translation unit):
       // Log.h  
       static void Log(const char* message) { /*...*/ }  // Local to each file  
      

4. Static Functions & Variables

  • static Keyword: Limits symbol visibility to the current .cpp file.
    // Math.cpp  
    static int Multiply(int a, int b) {  // Only visible in Math.cpp  
        Log("Multiply");  
        return a * b;  
    }  
    
    • No linker errors if Multiply is not used outside Math.cpp.

5. Header File Pitfalls

A. Accidental Duplicate Definitions

  • Problem: Including a function definition in a header used by multiple .cpp files.
    // Log.h  
    void Log(const char* message) {  // Defined in header → Duplicates!  
        std::cout << message << std::endl;  
    }  
    
    // Main.cpp  
    #include "Log.h"  // Copies Log() into Main.cpp  
    
    // Log.cpp  
    #include "Log.h"  // Copies Log() into Log.cpp → Conflict!  
    

    Fix: Always declare in headers, define in one .cpp.


B. Signature Mismatches

  • Example: Declaration vs. definition mismatch:
    // Main.cpp  
    void Log(const char* message);  // Declaration (no parameters)  
    
    // Log.cpp  
    void Log() { /*...*/ }  // Definition → Linker error!  
    
    error LNK2019: unresolved external symbol "void Log(char const*)"  
    

6. Best Practices

  1. Headers for Declarations:
    // Log.h  
    #pragma once  
    void Log(const char* message);  // Declaration  
    
  2. Source Files for Definitions:
    // Log.cpp  
    #include "Log.h"  
    void Log(const char* message) {  // Single definition  
        std::cout << message << std::endl;  
    }  
    
  3. Use inline for Small Functions:
    // Math.h  
    inline int Add(int a, int b) { return a + b; }  // Safe in headers  
    
  4. Avoid static Globally: Use only for translation-unit-specific helpers.

Key Takeaways

  • Compiler checks syntax; Linker connects symbols.
  • LNK2019: Missing definition.
  • LNK1169: Duplicate definitions.
  • Headers: Declarations only (use inline/static if definitions are needed).

▶️ Full Video Reference