Compiler and linker errors
C++ “multiple definition of” linker error explained
A “multiple definition of” error means the linker found more than one definition for the same external symbol. A common cause is putting a non-inline function or global variable definition in a header included by multiple .cpp files. Each source file compiles, but linking the object files creates duplicate definitions.
Understand separate compilation
A header is text included into each source file that names it. If two translation units include a header containing a regular function body, both translation units contain a definition. The compiler handles each translation unit separately, so the duplicate usually appears only at the link step. GCC labels it “multiple definition of”; MSVC commonly reports LNK2005.
A declaration announces a function's signature. A definition also provides its body. Put ordinary non-inline function declarations in headers and put one definition in one .cpp file. Include the header wherever code calls the function. This keeps the declaration shared while the implementation enters the final program once.
The same rule applies to external global variables. A header should normally declare a shared variable with extern. One source file defines it. A namespace-scope variable initialized in a header is a definition, not merely a promise that another file will provide storage.
Move function definitions out of headers
This failing project has two source files. Both include render.h, and that header defines renderAmount. Both object files then define the same function. The linker cannot choose one because both are definitions with external linkage.
Failing case: render.h
#pragma once
int renderAmount(int value) {
return value + 3;
}
Failing case: main.cpp
#include <iostream>
#include "render.h"
void auditRender();
int main() {
auditRender();
std::cout << "amount=" << renderAmount(4) << '\n';
return 0;
}
Failing case: audit.cpp
#include "render.h"
void auditRender() {
(void)renderAmount(1);
}
Build with g++ -std=c++17 main.cpp audit.cpp -o render-demo. GCC diagnostic core:
multiple definition of `renderAmount(int)'; <object>:<source>:(.text+0x0): first defined here
The text after the semicolon names the object file and source file that already defined the symbol. That source is usually the second .cpp file that included the same header. MSVC reports a duplicate external function with LNK2005, followed by LNK1169: one or more multiply defined symbols found. The fix keeps the declaration in the header and moves the body to one implementation file.
Fixed case: render.h
#pragma once
int renderAmount(int value);
Fixed case: render.cpp
#include "render.h"
int renderAmount(int value) {
return value + 3;
}
Fixed case: main.cpp
#include <iostream>
#include "render.h"
void auditRender();
int main() {
auditRender();
std::cout << "amount=" << renderAmount(4) << '\n';
return 0;
}
Fixed case: audit.cpp
#include "render.h"
void auditRender() {
(void)renderAmount(1);
}
Build the fixed files with g++ -std=c++17 main.cpp audit.cpp render.cpp -o render-demo.
Expected output:
amount=7
A C++17 inline function may have the same definition in several translation units, so a small function body can live in a header when it is marked inline. The keyword does not require the compiler to substitute the function body at each call. It changes the definition rule. Do not mark an arbitrary implementation inline merely to hide a project structure problem.
Declare shared global variables once
A global variable definition allocates the object. If a header contains int retryCount = 0;, each including translation unit gets a definition. Instead, put extern int retryCount; in the header and define int retryCount = 0; in exactly one source file. Other source files include the header and refer to that same object.
C++17 also supports inline variables. An inline variable can have a definition in a header included by multiple translation units. Use that for small shared constants or variables when the header definition is appropriate. For a mutable program-wide counter, a single extern declaration plus one definition makes ownership easier to see.
When a multiple-definition message names main, check for two entry-point source files in the build command. When it names a function or global, search headers for a body or initializer and identify every translation unit that includes it. Include guards and #pragma once stop repeated inclusion within one translation unit; they do not prevent the header from appearing in multiple source files.
Redefinition of 'int main()'
A redefinition of 'int main()' is a compile-time error when one translation unit contains two function definitions with that name. This differs from the linker error above: the compiler rejects the source before it creates object files. Including a .cpp file that defines main can produce the same problem.
Failing example: two definitions in one source file
int main() {
return 0;
}
int main() {
return 1;
}
GCC diagnostic core:
error: redefinition of 'int main()'
The exact wording varies by compiler and version. MSVC reports C2084 because the function already has a body.
Exercise
Fix the shared setting so two source files can include its header without defining the variable twice. Read a base value, add the setting, and print the result. Sample input:
4
Failing exercise: main.cpp
#include <iostream>
#include "settings.h"
void verifySetting();
int main() {
int amount = 0;
if (!(std::cin >> amount)) {
return 1;
}
verifySetting();
std::cout << amount + adjustment << '\n';
return 0;
}
Failing exercise: settings.h
#pragma once
int adjustment = 1;
Failing exercise: audit.cpp
#include "settings.h"
void verifySetting() {
(void)adjustment;
}
Build with g++ -std=c++17 main.cpp audit.cpp -o setting-demo. GCC diagnostic core:
multiple definition of `adjustment'
The exact wording varies by compiler and version. MSVC reports the duplicate external variable with LNK2005. Expected output after the fix:
5
Hint 1: Put an extern declaration in the header. Hint 2: Define the integer in one source file.
Show one possible solution
main.cpp
#include <iostream>
#include "settings.h"
void verifySetting();
int main() {
int amount = 0;
if (!(std::cin >> amount)) {
return 1;
}
verifySetting();
std::cout << amount + adjustment << '\n';
return 0;
}
settings.h
#pragma once
extern int adjustment;
settings.cpp
#include "settings.h"
int adjustment = 1;
audit.cpp
#include "settings.h"
void verifySetting() {
(void)adjustment;
}
Related guides
- Fix a name that was not declared
- Read no-matching-function errors
- Find an expected-semicolon error
- Understand undefined-reference errors
Keep learning with CppPath
Continue with the Header & Source Files lesson. The full lesson includes a quiz and a checked coding challenge with a free account.