Main Content

MISRA C++:2023 Rule 19.2.1

Precautions shall be taken in order to prevent the contents of a header file being included more than once

Since R2024b

Description

Rule Definition

Precautions shall be taken in order to prevent the contents of a header file being included more than once.

Rationale

When a translation unit contains a complex hierarchy of nested header files, it is possible for a particular header file to be included more than once, leading to confusion. If this multiple inclusion produces multiple or conflicting definitions, then your program can have undefined or erroneous behavior.

For instance, suppose that a header file contains:

#ifdef _WIN64
   int env_var;
#elseif  
   long int env_var;
#endif
If the header file is contained in two inclusion paths, one that defines the macro _WIN64 and another that undefines it, you can have conflicting definitions of env_var.

To avoid multiple inclusion of the same file, add include guards to the beginning of header files. Use either of these formats:

  • <start-of-file>
    // Comments allowed here
    #if !defined ( identifier )
    #define identifier
    // Contents of file
    #endif
    <end-of-file>
    
  • <start-of-file>
    // Comments allowed here
    #ifndef identifier
    #define identifier
    // Contents of file
    #endif
    <end-of-file>

Polyspace Implementation

The checker reports a violation if a header file does not contain an include guard or contains an incorrectly formatted include guard.

For instance, this code uses an include guard for the #define and #include statements. This code does not violate the rule:

// Contents of a header file
#ifndef FILE_H
#define FILE_H
#include "libFile.h"
#endif
If you use include guards that do not adhere to the suggested format, Polyspace® flags them. For instance:

  • You might mistakenly use different identifiers in the #ifndef and #define statements:

    #ifndef MACRO
    #define MICRO
    //...
    #endif

  • You might inadvertently use #ifdef instead of #ifndef or omit the #define statement.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

file1.hfile2.hmainfile.cpp
#ifndef MACRO
#define MICRO
//...
#endif
#ifdef DO_INCLUDE
#define DO_INCLUDE
void foo();
#endif
#include"file1.h"
#include"file2.h"
int main(){
	return 0;
}

In this example, two header files are included in the file mainfile.cpp.

  • The include guard in file1.h queries the definition of MACRO but conditionally defines a different identifier MICRO, perhaps inadvertently. This include guard is incorrectly formatted. Polyspace flags the file.

  • The include guard in file2.h uses #ifdef instead of #ifndef. This include guard is incorrect and Polyspace flags the file.

Check Information

Group: Preprocessing Directives
Category: Required

Version History

Introduced in R2024b