Dav*_*545 6 c optimization gcc compilation
基于这篇非常好的博客文章,严格的别名情况非常糟糕,我已经将这段代码放在网上供您测试:
http://cpp.sh/9kht(输出在-O0和-O2之间变化)
#include <stdio.h>
long foo(int *x, long *y) {
*x = 0;
*y = 1;
return *x;
}
int main(void) {
long l;
printf("%ld\n", foo((int *)&l, &l));
}
Run Code Online (Sandbox Code Playgroud)
这里有某种未定义的行为吗?
当我们选择-O2级别时,内部会发生什么?
zwo*_*wol 12
是的,这个程序有未定义的行为,因为基于类型的别名规则,可以概括为"你不能通过类型B的指针访问用类型A声明的内存位置,除非 B是指向字符类型的指针(例如unsigned char *
)." 这是近似值,但它足够接近大多数用途.注意,当A是指向字符类型的指针时,B可能不是别的东西 - 是的,这意味着通过一个uint32_t*
未定义的行为来访问字节缓冲区"一次四个"的常见习惯用法(博客文章也触及了这个).
编译器假定,编译时foo
,这x
和y
可能不指向同一个对象.从这一点来看,它推断写入*y
不能改变其值*x
,它只能返回已知值*x
0,而无需从内存中重新读取它.它只在打开优化时执行此操作,因为跟踪每个指针可以和不能指向的内容是昂贵的(因此编译速度较慢).
请注意,这是一个"恶魔飞出你的鼻子"的局面:编译有权作出生成的代码foo
下手
cmp rx, ry
beq __crash_the_program
...
Run Code Online (Sandbox Code Playgroud)
(像UBSan这样的工具可能会这样做)
归档时间: |
|
查看次数: |
99 次 |
最近记录: |