当优化关闭时,任何流行的编译器都会利用未定义的行为吗?

Syl*_*ert 0 c undefined-behavior

该博客声称:

  • 未定义的行为仅在高优化级别(例如 -O2 或 -O3)下“发生”。
  • 如果我使用 -O0 之类的标志关闭优化,那么就没有 UB。

都是假的。我想知道是否有任何现实世界的展示可以证明这一点。

例如,n << 1当 时触发 UB n<0。对于以下函数:

void foo(int n) {
  int t = n<<1;
  if (n>=0)
    nuke();
}
Run Code Online (Sandbox Code Playgroud)

编译器可以谨慎地编译它:

void foo(int n) {
  int t = n>=0 ? (n*2) : error("lshift negative int");
  if (n>=0)
    nuke();
}
Run Code Online (Sandbox Code Playgroud)

或通常:

void foo(int n) {
  int t = n*2;
  if (n>=0)
    nuke();
}
Run Code Online (Sandbox Code Playgroud)

或者积极优化它:

void foo(int n) {
  // unused
  // int t = n<<1;

  // always true, otherwise UB
  // if (n>=0)
    nuke();
}
Run Code Online (Sandbox Code Playgroud)

是否有像 gcc/clang 这样的现代流行编译器以最后一种方式运行,其中某些 UB 不仅会在该语句本地导致意外行为,而且还可能被故意利用(不考虑缓冲区溢出攻击等)并污染控制流在全球范围内,即使-O0指定了?

简而言之,所有 UB实际上都是在某种程度上实现定义的吗-O0

==编辑==

问题不在于这些主张在理论上是否错误或无意义(因为它们确实是)。而是是否有现实世界的展示。正如 @nate-eldredge 在评论中重新表述的那样:

给定一些形式上为 UB 的代码,现实生活中的非优化编译器会产生特别令人惊讶的结果(以上述方式),即使对于知识渊博的程序员来说也是如此?

P__*_*J__ 6

    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.
Run Code Online (Sandbox Code Playgroud)

这是错误的,原因之一。C 语言中未定义的内容在 C 标准中已定义。未定义行为意味着从C语言的角度来看,我们不知道程序将如何表现。UB 不必以任何特定方式表达自己 - 但它仍然是 UB。

这些说法源于不了解 UB 是什么。UB 不会“发生”。它们处于C语言级别。即使程序“运行良好”,它仍然是 UB。由于行为未定义,如果您更改编译器、编译器版本、编译器选项或在其他操作系统或硬件上运行,它可能会停止工作。