CodeQL 文档

缺少头文件保护

ID: cpp/missing-header-guard
Kind: problem
Security severity: 
Severity: recommendation
Precision: high
Tags:
   - efficiency
   - maintainability
   - modularity
   - external/jsf
Query suites:
   - cpp-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

一些头文件,例如定义结构或类的头文件,不能在同一个翻译单元中包含多次,因为这样做会导致重新定义错误。这样的头文件必须使用保护措施来防止多次包含带来的负面影响。类似地,如果头文件包含其他头文件,并且此包含图包含循环,则循环中的至少一个文件必须包含头文件保护措施才能打破循环。由于这些情况,所有头文件都应该使用保护措施,即使它们并非严格需要使用保护措施也是如此。

此外,大多数现代编译器包含由头文件保护措施触发的优化功能。如果头文件保护措施严格符合编译器预期的模式,则除第一次包含之外的所有包含将没有任何效果:文件不会从磁盘重新读取,也不会重新标记或重新预处理。这可以带来明显的,尽管很小的,编译时间改进。

建议

在文件中添加以下头文件保护措施之一(其中 HEADER_NAME 是从文件名派生的唯一标识符)

  1. #ifndef HEADER_NAME 后面跟着 #define HEADER_NAME 位于头文件的开头,最后使用匹配的 #endif 结尾。

  2. #if !defined(HEADER_NAME) 后面跟着 #define HEADER_NAME 位于头文件的开头,最后使用匹配的 #endif 结尾。

  3. #pragma once 位于头文件中的任何位置。请注意,如果您要更新代码以匹配联合攻击战斗机空战车辆编码标准,则第一个选项是唯一合适的形式。

示例

以下头文件的作者试图使用头文件保护措施,但打错了一个字

#ifndef MY_HAEDER_H
#define MY_HEADER_H

/* ... contents of my_header.h ... */

#endif

在这样的情况下,MY_HAEDER_H 应该替换为 MY_HEADER_H(注意 AE 的位置互换)

#ifndef MY_HEADER_H
#define MY_HEADER_H

/* ... contents of my_header.h ... */

#endif

示例

以下头文件似乎有保护措施,但并不完全符合规则

#ifdef __linux__
#ifndef MY_LINUX_ONLY_HEADER_H
#define MY_LINUX_ONLY_HEADER_H

/* ... contents of my_linux_only_header.h ... */

#endif // MY_LINUX_ONLY_HEADER_H
#endif // __linux__

尽管前面头文件中的预处理器指令可以防止重复包含带来的错误,但并非所有编译器都足够智能,能够识别它已被保护。因此,编译器优化将受到限制。为了确保编译器能够识别保护措施,更改头文件,使保护措施成为最外层的指令

#ifndef MY_LINUX_ONLY_HEADER_H
#define MY_LINUX_ONLY_HEADER_H
#ifdef __linux__

/* ... contents of my_linux_only_header.h ... */

#endif // __linux__
#endif // MY_LINUX_ONLY_HEADER_H

示例

以下头文件随着时间的推移而不断发展,不同的作者在不同位置添加函数声明

void alpha();

#ifndef MY_FUNCTIONS_H

void beta();

#define MY_FUNCTIONS_H

void gamma();
void delta();
void epsilon();

#endif

void omega();

不幸的是,结果是某些声明位于初始 #ifndef 之前,某些声明位于 #ifndef#define 之间,还有一些声明位于最终 #endif 之后。为了将此文件转换为正确保护的头文件,必须解决所有这三点问题

#ifndef MY_FUNCTIONS_H
#define MY_FUNCTIONS_H

void alpha();
void beta();
void gamma();
void delta();
void epsilon();
void omega();

#endif

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私