Kon*_*rov 4 c gcc clang compiler-optimization
有简单的代码,其中 clang 和 gcc 的行为不同。
int t;
extern void abort (void);
int f(int t, const int *a)
{
const int b[] = { 1, 2, 3};
if (!t)
return f(1, b);
return b == a;
}
int main(void)
{
if (f(0, 0))
abort ();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
铛:
> clang -v
clang version 4.0.1 (tags/RELEASE_401/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
> clang test.c
> ./a.out
Aborted
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会:
> gcc -v
Target: x86_64-suse-linux
Thread model: posix
gcc version 7.2.0 (GCC)
> gcc test.c
> ./a.out
> echo $?
0
Run Code Online (Sandbox Code Playgroud)
原因很明显:行为是由实现定义的,并且 clang 将常量本地数组合并到全局数组。
但可以说我想要一致的行为。我可以在 clang 中打开或关闭一些开关来禁用此优化并使其诚实地为不同的堆栈帧创建不同的本地数组(甚至是常量数组)吗?
您正在寻找的 clang 选项是-fno-merge-all-constants
. -fmerge-all-constants
如果你想达到相反的效果,你可以在 gcc 中启用它。但 gcc 中该选项的文档让我很好奇:
C 或 C++ 等语言要求每个变量(包括递归调用中同一变量的多个实例)具有不同的位置,因此使用此选项会导致不一致的行为。
唯一可能以某种方式表明 clang 可以逃脱惩罚的一点是(C11,6.5.2.4):
- 字符串文字和具有 const 限定类型的复合文字不需要指定不同的对象。
这里的问题是您的代码没有复合文字。
事实上,clang 有一个关于此问题的错误报告,开发人员似乎意识到这是不合格的:https://bugs.llvm.org/show_bug.cgi ?id=18538
里面有趣的评论是:
这是我能想到的(突然想到的)唯一一种情况,其中 clang 故意默认不符合标准,并且有一个标志使其符合标准。还有一些其他地方我们故意不遵守,因为我们认为标准是错误的(通常我们会尝试在这些情况下修复标准)。