EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)-根本原因

时间:2018-11-20 15:31:24

标签: c++ macos

EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)的根本原因是什么?在哪里记录?它是否与某处Intel CPU文档中的特定内容有关?

(在特定情况下,例如在使用Swift时,有很多关于此异常的问题,但是我盯着C ++程序的反汇编,对我在这里寻找的东西没有真正的了解。)

2 个答案:

答案 0 :(得分:2)

最可能的原因是您的代码具有某些未定义的行为。例如,以负索引写入数组。结果,在许多实现中,您最终要覆盖堆栈结构,并且下一次调用,返回或跳转使指令指针结束于数据而不是编译后的代码。

与调试器一起检查,如果运气好的话,足够多的堆栈会完整地告诉您问题可能出在哪里。如果不是,请运行某种类型的边界检查程序。以Valgrind为例。解决所有错误和警告。

答案 1 :(得分:2)

标识符"EXC_BAD_INSTRUCTION"似乎表明试图执行无效的操作码。在IA32硬件上,这是类型为Invalid Opcode Exception(#UD)的故障,中断向量值为6。可以出于多种原因触发该错误,但这通常意味着对传入指令进行编码的字节序列无效或保留,或者相对于指令而言操作数不一致,或者是较长(> 15字节),或者使用当前硬件不支持的IA32扩展,或者是UD2操作码,或者尝试在机器处于运行状态时执行某些指令一些阻止执行的状态,或其他一些极端情况。

现在,引起这种故障的一种可能解释是,您使用的编译器假定目标(执行)机器可以访问某些硬件功能,并相应地编译代码。通常可以将目标计算机功能指定为编译标志选项。例如,浮点运算和标准数学函数通常仅生成x87 fpu指令,但结合使用-mfpmath = sse和-msse指令编译器来生成SSE标量指令以进行常规浮点计算。 SEE指令集是IA32体系结构的扩展功能,并非在所有机器上都可用。用于体系结构的可移植代码应编译为该体系结构的独立于机器的通用代码。

此硬件故障的另一个可能但不太可能的原因是,编译器本身可能已被调试并生成了一些无效的字节序列。

我认为某些未定义的行为不会在大多数体系结构上导致无效的操作码错误。虽然UB可能导致任何形式的错误行为都是正确的,但是UB条件在编译时几乎永远无法检测到,因此通常会在IA32上生成通用保护错误(#GP)(在UNIX中称为分段错误)术语)。相反,尝试生成未定义的操作码是在编译时始终可检测到的条件(除非代码在运行时自行生成,或者字节码流未对齐且指令指针指向某些操作码的中间)