...
| Code Block | ||||
|---|---|---|---|---|
| ||||
// a.h
#ifndef A_HEADER_FILE
#define A_HEADER_FILE
namespace {
int v;
}
#endif // A_HEADER_FILE
// a.cpp
#include "a.h"
#include <iostream>
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();
g();
} |
When executed, this program will print:
...
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, resulting in the expected behavior:
| 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" #include <iostream> int v; // ExternallyDefinition usedof by get_v(); intglobal variable v; void f() { int i = get_v()std::cout << "f(): " << v << std::endl; v = 42; // ... } // b.cpp #include "a.h" #include <iostream> void g() { std::cout << "g(): " << v << std::endl; int i = get_v(); // ... }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 will print:
| Code Block |
|---|
f(): 0
g(): 42
f(): 100
g(): 42 |
Risk Assessment
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.
...