"Illegal hardware instruction" from very simple code

luq*_*qui 8 c standards undefined-behavior

While investigating a dubious claim, I wrote this little test program noway.c

int proveit()
{
    unsigned int n = 0;
    while (1) n++;
    return 0;
}

int main()
{
    proveit();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Testing this, I get:

$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction  ./a.out
Run Code Online (Sandbox Code Playgroud)

Wat.

如果我不进行优化就进行编译,则它会按预期挂起。我看了看程序集,没有所有的花哨main功能,函数看起来像这样:

_main:                                  ## @main
    pushq   %rbp
    movq    %rsp, %rbp
    ud2
Run Code Online (Sandbox Code Playgroud)

其中ud2显然是一个指令专门为未定义行为。前面提到的可疑声明“永不返回的函数是UB”得到了增强。我仍然很难相信。真!?您不能安全地编写自旋循环吗?

所以我想我的问题是:

  1. 这是对正在发生的事情的正确阅读吗?
  2. 如果是这样,有人可以指出我的官方资源吗?
  3. 您希望在哪种情况下进行这种优化?

相关资料

$ clang --version
Apple clang version 11.0.0 (clang-1100.0.20.17)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Run Code Online (Sandbox Code Playgroud)

M.M*_*M.M 4

如果您获得问题中现在的代码的 ud2,则该编译器不是符合标准的 C 编译器。您可以报告编译器错误。

请注意,在 C++ 中,此代码实际上是 UB。当添加线程(分别是 C11 和 C++11)时,任何线程都会有前向进度保证,包括非多线程程序的主执行线程。

在 C++ 中,所有线程最终都必须进行,无一例外。然而,在 C 中,控制表达式为常量表达式的循环不需要继续进行。我的理解是,C 添加了这个异常,因为在嵌入式编码中使用 awhile(1) {}来挂起线程已经是常见的做法。

类似问题,有更详细的答案