Main Content

Unnamed namespace in header file

Header file contains unnamed namespace leading to multiple definitions

Description

This defect occurs when an unnamed namespace is used in a header file, which can lead to multiple definitions of objects in the namespace.

Risk

According to the C++ standard, names in an unnamed namespace, for instance, aVar:

namespace {
   int aVar;
}
have internal linkage by default. If a header file contains an unnamed namespace, each translation unit with a source file that #include-s the header file defines its own instance of objects in the namespace. The multiple definitions are probably not what you intended and can lead to unexpected results, unwanted excess memory usage, or inadvertently violating the one-definition rule.

Fix

Specify names for namespaces in header files or avoid using namespaces in header files.

Examples

expand all

Header File: aHeader.h

namespace {
   int aVar;
}

First source file: aSource.cpp

#include "aHeader.h"
#include <iostream>

void setVar(int arg) {
    std::cout << "Current value: " << aVar << std::endl;
    aVar = arg;
    std::cout << "Value set at: " << aVar << std::endl;
}

Second source file: anotherSource.cpp

#include "aHeader.h"
#include <iostream>

extern void setVar(int);

void resetVar() {
    std::cout << "Current value: " << aVar << std::endl;
    aVar = 0;
    std::cout << "Value set at: 0" << std::endl;
}

void main() {
    setVar(1);
    resetVar();
}

In this example, the unnamed namespace leads to two definitions of aVar in the translation unit from aSource.cpp and the translation unit from anotherSource.cpp. The two definitions lead to possible unexpected output:

Current value: 0
Value set at: 1
Current value: 0
Value set at: 0

Correction – Avoid the Unnamed Namespace

One possible correction is to avoid a namespace in the header file.

Header File: aHeader.h

extern int aVar;

First source file: aSource.cpp

#include "aHeader.h"
#include <iostream>

void setVar(int arg) {
    std::cout << "Current value: " << aVar << std::endl;
    aVar = arg;
    std::cout << "Value set at: " << aVar << std::endl;
}

Second source file: anotherSource.cpp

#include "aHeader.h"
#include <iostream>

extern void setVar(int);
int aVar;

void resetVar() {
    std::cout << "Current value: " << aVar << std::endl;
    aVar = 0;
    std::cout << "Value set at: 0" << std::endl;
}

void main() {
    setVar(1);
    resetVar();
}

You now see the expected sequence in the output:

Current value: 0
Value set at: 1
Current value: 1
Value set at: 0

Result Information

Group: Programming
Language: C++
Default: On for handwritten code, off for generated code
Command-Line Syntax: UNNAMED_NAMESPACE_IN_HEADER
Impact: Medium

Version History

Introduced in R2019b