c - "Illegal hardware instruction"来自非常简单的代码

标签 c standards undefined-behavior

调查时a dubious claim ,我写了这个小测试程序noway.c

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

int main()
{
    proveit();
    return 0;
}

对此进行测试,我得到:

$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction  ./a.out

瓦。

如果我在没有优化的情况下进行编译,它会按预期挂起。我查看了程序集,没有所有花里胡哨的 main 函数如下所示:

_main:                                  ## @main
    pushq   %rbp
    movq    %rsp, %rbp
    ud2

其中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

最佳答案

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

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

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

Similar question with more detailed answers

关于c - "Illegal hardware instruction"来自非常简单的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59080105/

相关文章:

c - 在 C 中反转字符串 - 内存方向

c - 如何在 Mac 上从 C 访问 macOS API 调用?

c - 内核链表内核 Oops

c++ - C++中结构/类的历史是什么?

c++ - `y=++y`,这个标准符合吗? [出现在微软的测试中]

c - 在理解 char->ASCII 和一些基础知识方面需要一些帮助

c - 指向常量结构的速记 typedef 指针

c - C语言中free的奇怪(未定义?)行为

c++ - 根据 C++ 标准,该程序在哪个确切语句中表现出未定义的行为?

c - block 作用域链接 C 标准