JPCERT コーディネーションセンター

PRE06-C. ヘッダファイルはインクルードガードで囲む

1980年代初頭まで、大規模なソフトウェア開発プロジェクトはヘッダのインクルードについて度重なる問題に遭遇していた。たとえば、あるグループが graphics.h を作成し、このヘッダの冒頭で io.h をインクルードする。一方、他のグループが keyboard.h を作成し、これもまた io.h をインクルードする。もし io.h を安全に複数回インクルードすることができなければ、どのヘッダが io.h をインクルードするべきかという議論が起こる。あるアプリケーションプログラムの例では、どのヘッダも他のヘッダを一切インクルードしてはならないという取り決めがされ、プログラムコードは数十もの #include 行から始まることになった。その結果、インクルードの順序を間違えたり、必要なヘッダを忘れてしまったりという問題が発生した。

適合コード

これらの混乱は単純な手法の発見により解決した。それは、各ヘッダで「自分はすでにインクルードされています」を意味するシンボルを定義する(#defineする)という方法である。ヘッダ全体を次のようにインクルードガードで囲むのである。

#ifndef HEADER_H
#define HEADER_H

/* ... <header.h> の内容がここに入る */

#endif /* HEADER_H */

これにより、header.h は最初の #include でその内容がすべてインクルードされる。このヘッダが続いてもう一度 #include されると、その内容はバイパスされる。

このような方法を使うことで複数回インクルードできるヘッダファイルを作成できる。C標準では、標準ヘッダは複数回インクルードされても安全であることを保証している。

インクルードガードで使用するマクロの名前に予約済みの識別子を使用するのはよくある誤りであり、注意が必要である。「DCL37-C. 予約済みの識別子を宣言または定義しない」を参照。

リスク評価

ヘッダファイルをインクルードガードで囲み忘れると予期せぬ動作を引き起こすおそれがある。

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

PRE06-C

P3

L3

自動検出
ツール バージョン チェッカー 説明
Astrée
17.04i
multiple-include 一部実装済み

ECLAIR

1.2

CC2.PRE06

実装済み
Klocwork
2017
MISRA.INCGUARD
LDRA tool suite
9.7.1

243 S

実装済み
Parasoft C/C++test 10.3 PFO-02 実装済み
PRQA QA-C
9.3
0883 実装済み
RuleChecker
17.04i
multiple-include 一部実装済み
関連するガイドライン
SEI CERT C++ Coding Standard VOID PRE06-CPP. Enclose header files in an include guard
MISRA C:2012 Directive 4.10 (required)
参考資料
[Plum 1985] Rule 1-14
翻訳元

これは以下のページを翻訳したものです。

PRE06-C. Enclose header files in an include guard (revision 92)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter