メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

CERT C++: DCL59-CPP

Do not define an unnamed namespace in a header file

説明

ルール定義

Do not define an unnamed namespace in a header file.1

Polyspace 実装

ルール チェッカーは、"ヘッダー ファイルの無名の名前空間" をチェックします。

すべて展開する

問題

ヘッダー ファイルの無名の名前空間は、ヘッダー ファイルに含まれる無名の名前空間を検出します。名前空間が無名であると、その内部のオブジェクトが複数の定義をもつ可能性があります。

リスク

C++ 規格によると、無名の名前空間内の名前 (たとえば、次の aVar) は、

namespace {
   int aVar;
}
既定では内部リンクをもちます。ヘッダー ファイルが無名の名前空間を含む場合、ヘッダー ファイルを #include する各翻訳単位が、その名前空間内の自身のオブジェクト インスタンスを定義します。通常、オブジェクトを意図的に複数定義することはないため、メモリの過剰使用、単一定義ルールの違反など、予期しない結果を引き起こす可能性があります。

修正方法

ヘッダー ファイルの名前空間に名前を指定するか、ヘッダー ファイルの名前空間を使わないようにします。

例 – ヘッダー ファイルの無名の名前空間に起因する予期しない結果

ヘッダー ファイル: aHeader.h

namespace { //Noncompliant
   int aVar;
}

1 つ目のソース ファイル: 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;
}

2 つ目のソース ファイル: 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 の定義が 2 つ、aSource.cpp の翻訳単位内と、anotherSource.cpp の翻訳単位内に存在することになります。定義が 2 つあるため、次のような予期しない出力がなされる可能性もあります。

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

修正 – 名前空間が無名にならないようにする

1 つの修正方法として、単純にヘッダー ファイルの名前空間を回避します。

ヘッダー ファイル: aHeader.h

extern int aVar;

1 つ目のソース ファイル: 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;
}

2 つ目のソース ファイル: 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

チェック情報

グループ: 01.宣言と初期化 (DCL)

バージョン履歴

R2019a で導入


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.