How the C++ Linker Works - ▶️YouTube
Key Concepts
1. Compilation vs. Linking
- Compilation: Converts
.cppfiles to.objfiles (machine code).- Shortcut:
Ctrl + F7(Visual Studio) compiles without linking. - Errors: Syntax issues (e.g., missing semicolons, type mismatches).
- Shortcut:
- Linking: Combines
.objfiles into an executable, resolving symbols (functions/variables).- Shortcut:
F5(VS) compiles + links + runs. - Errors: Missing/multiple definitions (e.g.,
LNK2019,LNK1169).
- Shortcut:
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
.cppfile.
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 fileserror LNK2005: "void Log(char const*)" already defined in Log.objFix:
- 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 - Use
inline(for small functions):// Log.h inline void Log(const char* message) { /*...*/ } // No duplication - Use
static(limits visibility to translation unit):// Log.h static void Log(const char* message) { /*...*/ } // Local to each file
- Declare in header, define in one
4. Static Functions & Variables
staticKeyword: Limits symbol visibility to the current.cppfile.// Math.cpp static int Multiply(int a, int b) { // Only visible in Math.cpp Log("Multiply"); return a * b; }- No linker errors if
Multiplyis not used outsideMath.cpp.
- No linker errors if
5. Header File Pitfalls
A. Accidental Duplicate Definitions
- Problem: Including a function definition in a header used by multiple
.cppfiles.// 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
- Headers for Declarations:
// Log.h #pragma once void Log(const char* message); // Declaration - Source Files for Definitions:
// Log.cpp #include "Log.h" void Log(const char* message) { // Single definition std::cout << message << std::endl; } - Use
inlinefor Small Functions:// Math.h inline int Add(int a, int b) { return a + b; } // Safe in headers - Avoid
staticGlobally: 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/staticif definitions are needed).
