在this blog中声称:
- 未定义的行为仅在高优化级别(如-O2或-O3)下“发生”。
- 如果我用-O 0这样的标志关闭优化,那么就没有UB。
都是假的。我想知道是否有任何现实世界的展示索赔。
例如,当n<0
时,n << 1
触发UB。对于以下功能:
void foo(int n) {
int t = n<<1;
if (n>=0)
nuke();
}
字符串
编译器可以谨慎地编译它:
void foo(int n) {
int t = n>=0 ? (n*2) : error("lshift negative int");
if (n>=0)
nuke();
}
型
或通常:
void foo(int n) {
int t = n*2;
if (n>=0)
nuke();
}
型
或者进行聚合优化:
void foo(int n) {
// unused
// int t = n<<1;
// always true, otherwise UB
// if (n>=0)
nuke();
}
型
有没有像gcc/clang这样的现代流行编译器以最后一种方式运行,其中一些UB不仅会在该语句中导致本地意外行为,而且还可能被故意利用(不考虑缓冲区溢出攻击等)并污染全局控制流,即使指定了-O0
?
简单地说,所有的UB实际上都是在-O0
下定义的实现吗?
==编辑==
问题不在于这些说法是否 * 理论上 * 是错误的或荒谬的(因为它们是)。关键在于是否有真实的展示。正如@nate-eldredge在评论中所述:
给定一段形式上是UB的代码,一个现实生活中的非优化编译器产生的结果是特别令人惊讶的(以上述方式),即使是一个相当有知识的程序员?
1条答案
按热度按时间az31mfrm1#
字符串
这是假的,原因只有一个。C语言中未定义的内容在C标准中定义。未定义的行为意味着从C语言的Angular 来看,我们不知道程序将如何行为。UB不需要以任何特定的方式表达自己-但它仍然是UB。
这些说法来自于不理解UB是什么。UB不会“发生”。它们是C语言级别的。即使程序“工作正常”,它仍然是UB。由于行为未定义,如果您更改编译器,编译器版本,编译器选项或在另一个操作系统或硬件上运行,它可能会停止工作。