为何GCC与Clang会优化掉static volatile变量的读取操作?
关于static+volatile函数指针被编译器优化的疑问
先给出基础定义代码:
typedef void foo_t(void); static void foo(void) { }
两种不同场景的编译结果
- 全局volatile函数指针:代码符合预期未被优化,指针会被读取,函数以间接(尾)调用方式执行:
foo_t volatile *gfoo = foo; void gtest() { gfoo(); }
- 静态volatile函数指针:读取操作与函数调用会被完全优化掉:
static foo_t volatile *sfoo = foo; void stest() { sfoo(); }
我的疑问与依据
我明白由于static的特性,编译器能看到sfoo从未被写入,因此会假设它始终指向同一个空函数,并尝试内联该函数。但我对volatile的理解是,它应该强制执行读取操作,且不对读取的数据做任何假设。
比如C99最终草案N1256的“6.7.3 类型限定符”中明确提到:
具有volatile限定类型的对象可能会以实现未知的方式被修改,或存在其他未知副作用。因此,任何引用此类对象的表达式都应严格按照5.1.2.3中描述的抽象机规则进行求值。[…]
相关讨论中也引用过这段内容,但因为这里的变量是被读取而非仅初始化,我认为sfoo不该被优化掉。
顺带一提,我是从一篇德语博客文章中了解到这个问题的,文章讨论了OpenSSL如何用类似方法防止死存储被优化。
内容的提问来源于stack exchange,提问作者wrtlprnft
相关产品推荐
相关产品推荐

