C非法指令

C illegal instruction

下面是我编写的 c 程序的打印输出,我的演示 运行,最后是关于我的编译器的一些信息。

➜  illegalInstructionDebug cat illegal.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void func(int* Z){
    Z[-11] = acos(2);
}

int main(){
    fflush(stdout);
    printf("");
    fflush(stdout);
    int X[3];
    int Z[3];
    for (int n=0;0!=0;);
    func(Z);
}
➜  illegalInstructionDebug gcc illegal.c; ./a.out
[1]    28836 illegal hardware instruction  ./a.out
➜  illegalInstructionDebug clang --version
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
➜  illegalInstructionDebug

我在编写程序时遇到了非法指令错误,这是我以前从未见过的错误,所以我决定尝试找到一个最小的工作示例,以便找出它与段错误或其他错误的区别其他类型的错误。奇怪的是,程序中的微小改动似乎会 return 给出段错误而不是非法指令错误。尽管如此,我还是设法将程序大幅缩减为一个更小的工作示例。话虽如此,对于最小的工作示例来说,该程序仍然相当大。

我的问题首先是为什么会出现非法指令错误,其次是什么是非法指令错误。此外,如果此错误特定于我的机器,我也会感兴趣。这个程序有很多奇怪的属性。例如,似乎需要数字 -11 才能导致错误。

这个

void func(int *Z){
    Z[-11] = acos(2);
}

很可能碰巧覆盖了堆栈中的某些 code 地址。很可能是 return 地址。由于堆栈在 x86-64 上向下增长,并且您正在将内容写入较低地址,这意味着 return 地址被放置在堆栈 after space for Z 是保留的,所以我想这会从 func() 命中 return 地址。更重要的是,您将覆盖 return 地址的 一半

acos(2) 是域错误,returns NaN 在我的 GCC 上转换为 int 导致 INT_MIN 被写在那里......你应该实际上使用调试器并查看发生崩溃的上下文,我猜它是在一个地址中,该地址在其十六进制表示中包含很多 fs。

当从 RIP 开始的字节未解码为有效的 x86-64 指令或 for other reasons.

时,将引发无效指令