C语言 当优化关闭时,是否有任何流行的编译器利用未定义的行为?

fhity93d  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(116)

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的代码,一个现实生活中的非优化编译器产生的结果是特别令人惊讶的(以上述方式),即使是一个相当有知识的程序员?

az31mfrm

az31mfrm1#

Undefined behavior only "happens" at high optimization levels like -O2 or -O3.
    If I turn off optimizations with a flag like -O0, then there's no UB.

字符串
这是假的,原因只有一个。C语言中未定义的内容在C标准中定义。未定义的行为意味着从C语言的Angular 来看,我们不知道程序将如何行为。UB不需要以任何特定的方式表达自己-但它仍然是UB。
这些说法来自于不理解UB是什么。UB不会“发生”。它们是C语言级别的。即使程序“工作正常”,它仍然是UB。由于行为未定义,如果您更改编译器,编译器版本,编译器选项或在另一个操作系统或硬件上运行,它可能会停止工作。

相关问题