One Definition Rule (ODR) is a fundamental rule of C++ that requires that within the entire program (across all translation units), there is exactly one definition for each object, function, or class.
ODR is violated if:
This leads to subtle, unpredictable bugs, incorrect linking, or worse, varying behavior of the program depending on how it was compiled.
Why violations occur:
In large projects, .h files are often copied/modified without version control, or code is separated into many modules with separate compilation. If someone changes an inline function in only one place, other source files may still have the old version.
How to avoid:
constexpr or, with C++17, inline variables.Can static functions (static void foo()) with the same names and different implementations be defined in different .cpp files without consequences?
Many believe that static functions do not affect each other across modules at all. The answer is yes, they can, because each has internal linkage (visible only within its translation unit). However, this is not guaranteed for inline functions and templates, which is often confused.
Example:
// file1.cpp static void foo() { std::cout << "A"; } // file2.cpp static void foo() { std::cout << "B"; }
Calls in these modules will be independent.
Story
In a large project, one developer changed the body of an inline function in only one of the clone .h files. After compilation, some behavior became unpredictable: some modules were operating under the old algorithm, while others were following the new one. The reason was an ODR violation for the inline function.
Story
During the migration to C++17, a constant variable was defined in several header files without using the inline keyword. During linking, many duplicate symbol errors appeared. It was fixed by declaring the variable as
inline const.
Story
It was discovered too late that the generated .h file of the build system contained two implementations of the same method of a template class, differing by one ifdef check in different builds. Later, the application periodically crashed due to ABI mismatches between the linked modules.