非适当场景禁用 volatile
6.2.10 ID_forbidVolatile
应在适当的场景中合理使用 volatile,否则会导致优化或同步相关的多种问题。
下列场景可使用 volatile:
- 对象读写对应外设 IO
- 与信号等中断处理过程共享对象
- 局部对象在 setjmp、longjmp 之间被修改
- 出于安全目的清理内存中的数据
- 在 C/C++ 之外,通过与编译优化不兼容的方式访问对象
在这些场景中,如果相关对象没有用 volatile 限定会导致程序和预期不符,volatile 关键字可以保证对象具有稳定的内存地址,任何读取或写入都可以来源于或作用于内存中的实际数据。
除此之外不应使用 volatile,不参与过程间跳转的局部 volatile 对象往往意味着 volatile 的滥用,审计工具不妨重点关注这种对象,而且要注意 volatile 和 C/C++ 的并发或同步机制没有直接关系,也无法保证相关操作的原子性。
示例:
volatile int x; // Non-compliant, ‘volatile’ is abused
void thd() {
LockGuard g;
read_and_write(x);
}
例中 x 是不涉及外设的共享对象,thd 是线程函数,LockGuard 是某种 RAII 锁,在已落实同步机制的情况下,不应再使用 volatile。
依据
ISO/IEC 9899:1999 6.7.3(6)
ISO/IEC 9899:2011 6.7.3(7)
ISO/IEC 14882:2003 7.1.5.1(8)
ISO/IEC 14882:2011 7.1.6.1(7)