Unnamed namespaces are used to define a namespace that is unique to the translation unit, where the names contained within have internal linkage by default. The C++ Standard, [namespace.unnamed], paragraph 1 [ISO/IEC 14882-2014], states the following:
An unnamed-namespace-definition behaves as if it were replaced by:
inline namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }where
inline
appears if and only if it appears in the unnamed-namespace-definition, all occurrences ofunique
in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the entire program.
...
When executed, this program prints the following:.
Code Block |
---|
f(): 0 g(): 0 f(): 42 g(): 100 |
...
In this compliant solution, v
is defined in only one translation unit but is externally visible to all translation units, resulting in the expected behavior:.
Code Block | ||||
---|---|---|---|---|
| ||||
// a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE extern int v; #endif // A_HEADER_FILE // a.cpp #include "a.h" #include <iostream> int v; // Definition of global variable v void f() { std::cout << "f(): " << v << std::endl; v = 42; // ... } // b.cpp #include "a.h" #include <iostream> void g() { std::cout << "g(): " << v << std::endl; v = 100; } int main() { extern void f(); f(); // Prints v, sets it to 42 g(); // Prints v, sets it to 100 f(); // Prints v, sets it back to 42 g(); // Prints v, sets it back to 100 } |
When executed, this program prints the following:.
Code Block |
---|
f(): 0 g(): 42 f(): 100 g(): 42 |
...
In this compliant solution, v
is defined in only one translation unit but is externally visible to all translation units and can be accessed from the inline get_v()
function:.
Code Block | ||||
---|---|---|---|---|
| ||||
// a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE extern int v; inline int get_v() { return v; } #endif // A_HEADER_FILE // a.cpp #include "a.h" // Externally used by get_v(); int v; void f() { int i = get_v(); // ... } // b.cpp #include "a.h" void g() { int i = get_v(); // ... } |
...
In this compliant solution, f()
is not defined with an unnamed namespace and is instead defined as an inline function. Inline functions are required to be defined identically in all the translation units in which they are used, which allows an implementation to generate only a single instance of the function at runtime in the event the body of the function does not get generated for each call site.
...
Defining an unnamed namespace within a header file can cause data integrity violations and performance problems but is unlikely to go unnoticed with sufficient testing. One-definition rule violations result in undefined behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
DCL59-CPP | Medium | Unlikely | Medium | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| unnamed-namespace-header | Fully checked | ||||||
Axivion Bauhaus Suite |
| CertC++-DCL59 | |||||||
Clang |
| cert-dcl59-cpp | Checked by clang-tidy | ||||||
CodeSonar |
| LANG.STRUCT.DECL.ANH | Anonymous Namespace in Header File | ||||||
Helix QAC |
| C++2518 | |||||||
Klocwork |
| MISRA.NAMESPACE.UNMD | |||||||
LDRA tool suite |
| 286 S, 512 S | Fully implemented | ||||||
Parasoft C/C++test |
| CERT_CPP-DCL59-a | There shall be no unnamed namespaces in header files | |||||||
Polyspace Bug Finder |
| CERT C++: DCL59-CPP | Checks for unnamed namespaces in header files (rule fully covered) | ||||||
RuleChecker |
| unnamed-namespace-header | Fully checked | ||||||
SonarQube C/C++ Plugin |
| UnnamedNamespaceInHeader |
PVS-Studio |
| V1068 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
[ISO/IEC 14882-2014] | Subclause 3.2, "One Definition Rule" |
...
...