exponenta event banner

Безымянное пространство имен в файле заголовка

Файл заголовка содержит безымянное пространство имен, что приводит к нескольким определениям

Описание

Этот дефект возникает, когда в файле заголовка используется безымянное пространство имен, что может привести к множеству определений объектов в пространстве имен.

Риск

Согласно стандарту C++, имена в безымянном пространстве имен, например, aVar:

namespace {
   int aVar;
}
по умолчанию имеют внутреннюю связь. Если файл заголовка содержит безымянное пространство имен, каждый блок перевода имеет исходный файл, который #include-s файл заголовка определяет собственный экземпляр объектов в пространстве имен. Несколько определений, вероятно, не то, что вы хотели, и могут привести к неожиданным результатам, нежелательному избыточному использованию памяти или непреднамеренному нарушению правила одного определения.

Зафиксировать

Укажите имена пространств имен в файлах заголовков или избегайте использования пространств имен в файлах заголовков.

Примеры

развернуть все

Файл заголовка: aHeader.h

namespace {
   int aVar;
}

Первый исходный файл: 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;
}

Второй исходный файл: 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();
}

В этом примере безымянное пространство имен приводит к двум определениям aVar в блоке перевода от aSource.cpp и блок перевода из anotherSource.cpp. Два определения приводят к возможным неожиданным результатам:

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

Исправление - избегайте безымянного пространства имен

Одной из возможных корректировок является исключение пространства имен в файле заголовка.

Файл заголовка: aHeader.h

extern int aVar;

Первый исходный файл: 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;
}

Второй исходный файл: 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();
}

Теперь в выходных данных отображается ожидаемая последовательность:

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

Информация о результатах

Группа: Программирование
Язык: C++
По умолчанию: Вкл для рукописного кода, выкл для сгенерированного кода
Синтаксис командной строки: UNNAMED_NAMESPACE_IN_HEADER
Воздействие: среднее
Представлен в R2019b