CertC-PRE06¶
Enclose header files in an include guard
Required inputs: IR
Until the early 1980s, large software development projects had a continual
problem with the inclusion of headers. One group might have produced a
graphics.h, for example, which started by including
io.h. Another group might have produced
keyboard.h, which also included
io.h. If
io.h could not safely be included several times, arguments would
break out about which header should include it. Sometimes an agreement was
reached that each header should include no other headers, and as a result, some
application programs started with dozens of
#include lines, and sometimes they got the ordering wrong or
forgot a required header.
Compliant Solution
All these complications disappeared with the discovery of a simple technique:
each header should
#define a symbol that means "I have already been included." The
entire header is then enclosed in an include guard:
#ifndef HEADER_H #define HEADER_H /* ... Contents of <header.h> ... */ #endif /* HEADER_H */
Consequently, the first time
header.h is
#include'd, all of its contents are included. If the header file
is subsequently
#include'd again, its contents are bypassed.
Because solutions such as this one make it possible to create a header file that can be included more than once, the C Standard guarantees that the standard headers are safe for multiple inclusion.
Note that it is a common mistake to choose a reserved name (such as
_HEADER_H_ or
__HEADER_H__) for the name of the macro used in the include guard.
See
DCL37-C.
Do not declare or define a reserved identifier for more information.
Risk Assessment
Failure to include header files in an include guard can result in unexpected behavior.
| Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| PRE06-C | Low | Unlikely | Low | P3 | L3 |
Related Guidelines
| SEI CERT C++ Coding Standard | VOID PRE06-CPP. Enclose header files in an include guard |
| MISRA C:2012 | Directive 4.10 (required) |
Bibliography
| [ Plum 1985] | Rule 1-14 |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
include_guard_missing |
Missing include guard. |
None |
False |
include_guard_partial |
Include guard does not cover complete file. |
None |
False |
include_guard_with_wrong_define |
Bad include guard: #define uses wrong macro, should be {}. |
None |
False |
include_guard_without_define |
Incomplete include guard: missing #define {}. |
None |
False |
Options¶
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
macro_name_restrictions¶
macro_name_restrictions : list[typing.Callable[[bauhaus.ir.Node, scanner.Token, typing.Optional[str]], typing.Optional[str]]] = []