Reputation: 2769
What are the underlying causes of EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) and where is it documented? Does it relate to a specific thing in the Intel CPU documentation somewhere maybe?
(There are lots of questions about this exception happening in specific cases, e.g. when using Swift, but I'm staring the disassembly of a C++ program and have no real understanding of what I'm looking for here.)
Upvotes: 2
Views: 2840
Reputation: 828
The identifier "EXC_BAD_INSTRUCTION"
seems to indicate an attempt to execute an invalid opcode. On IA32 hardware, it is a fault of type Invalid Opcode Exception (#UD) and has interrupt vector value of 6. It can be triggered for a number of reasons but it generally means that the byte sequence that encode the incoming instruction is invalid or reserved, or has inconsistent operands relative to the instruction, or is to long (>15 bytes), or uses an IA32 extension not supported by the current hardware, or is the UD2 opcode, or attempting to execute some instruction while the machine is in some state that prevents its execution, or some other corner cases.
Now, one possible explanation for cause for this kind of fault is that the compiler you are using assumes that some hardware features are accessible to the target (executing) machine and compiles code accordingly. The target machine features can generally specified as compile flag options. For example, floating point operations and standard math functions will normally only generate x87 fpu instruction, but using the combination of -mfpmath=sse and -msse instruct compiler to generate SSE scalar instructions for usual floating point calculations. The SEE instruction sets are an extension feature of IA32 architecture and are not available on all machines. Portable code for an architecture should be compiled to machine independent generic code for this architecture.
Another possible but less probable cause for this hardware fault is that the compiler might itself be bugged and generate some invalid byte sequence.
I don't think some undefined behavior would lead to an invalid opcode fault on most architectures. While it is true that UB may lead to any kind of erratic behavior, UB conditions are mostly never detectable at compile time and as such, the usually generate a General Protection Fault (#GP) on IA32 (which is called a segmentation fault in unix nomenclature). On the opposite, attempting to generate an undefined opcode is a condition that is always detectable at compile time (unless the code is self generating at runtime, or if the byte code stream gets misaligned and the instruction pointer points in the middle of some opcode).
Upvotes: 3
Reputation: 11430
The most likely reason is that your code has some undefined behavior. For example writing to an array at a negative index. As a result, on many implementations, you end up writing over the stack structure and the next call, return or jump has your instruction pointer ending over data instead of compiled code.
Check with a debugger and with some luck enough of the stack will be intact to tell you around were the issue might be. If not, run with some type of bounds checking program. Valgrind for example. Address all error and warnings.
Upvotes: 2