【发布时间】:2019-03-20 15:14:09
【问题描述】:
我有一个关于严格别名和 clang 优化的问题,例如。
让我们考虑下面的例子(1):
typedef void (*FTy)(void);
FTy F = 0;
(*F)();
这是一种未定义的行为。
让我们考虑下面的例子(2):
typedef void (*FTy)(void);
static const FTy F = 0;
void g( int flag)
{
if ( flag )
{
(*F)();
}
}
int main( void)
{
g( 0);
return (0);
}
F 的间接调用仍然是“未定义的行为”,但始终处于错误状态。所以程序一定是正确的。
现在让我们考虑主要示例 (3): (第二版:感谢@Antti Haapala 简化版) (第三版:always_inline的使用)
#include <stdio.h>
#ifndef BUGGY
#define BUGGY 1
#endif
static inline void __attribute__((always_inline)) longLongAssign( int cond, char *ptr)
{
if ( cond )
{
*((long long *)ptr) = 0;
}
}
void funcA(int s, int g)
{
int i, j = 0, k;
int grp[4] = {-1, -1};
void *ptr[2] = {(void *)&(grp[0]), 0};
for (i = 0, k = 0; i < 1; ++i) {
for (j = 0; j < 1; ++j) {
if ( grp[g] > 0 )
{
if ( g > 5 )
{
continue;
} else
{
longLongAssign( g > 3, (char *)ptr[0]);
}
}
grp[k++] = 0;
}
printf("this should be zero: %d\n", grp[0]);
}
}
int main(void) {
funcA(0, 1);
}
gcc编译并执行
this should be zero: 0
通过“clang-7.0 -O0”编译并执行
this should be zero: 0
通过“clang-7.0 -O1 -fno-strict-aliasing”编译并执行
this should be zero: 0
通过“clang-7.0 -O1”编译并执行
this should be zero: -1
在主要示例中,grp 的商店之一正式违反严格混叠
*((long long *)ptr) = 0;
但是这家商店总是处于虚假状态。
这里的问题是:商店如何运作
- 违反了严格的别名规则
- 但位于无法访问的语句中
可能会影响程序执行的任何方式?
C 语言标准是否正确?
下面的示例 (4) 是否正确、定义明确并且没有未定义的行为?
void assign( int type, char *ptr)
{
if ( ptr )
{
if ( (type == 0) )
{
*((int *)ptr) = 1;
} else if ( (type == 1) )
{
*((float *)ptr) = 1;
} else
{
// unknown type
}
}
}
int main( void)
{
int a;
float b;
assign( 0, (char *)&a);
assign( 1, (char *)&b);
assign( 0, (char *)0);
return (0);
}
函数 main 中的内联和常量传播优化给出
...
if ( &a )
{
if ( (0 == 0) )
{
*((int *)&a) = 1;
} else if ( (0 == 1) )
{
*((float *)&a) = 1;
} else
{
// unknown type
}
}
...
单手店铺运营
*((float *)&a) = 1;
正式违反严格别名,但处于无法访问的位置。
示例(4)可能不正确的原因有哪些? 如果示例(4)是正确的,那么为什么示例(3)通过 clang 编译给出不同的结果?
【问题讨论】:
-
@ensc 所以这不是最小的。我已经有了 clang 6.0.0 的行为并删除了 while 循环、函数 pointer 取消引用等......
-
longjmp也不需要。 -
@Павел 您是否同意this code 重现了问题 - 它更像是minimal reproducible example,并且更关注实际问题。
-
@JohnBollinger 循环似乎是必不可少的......而且数组需要 4 个元素而不是 2 个......
-
@Павел 但您是否同意它仍然会重现该问题 - 如果您可以使用您的 GCC、Clang 自己验证它,如果可以,请edit 这个问题包含它 - 并且后人,这是你作为问题作者应该做的练习。
标签: c optimization clang undefined-behavior strict-aliasing