Apple Silicon M1平台无理由SIGBUS崩溃问题求助
原生M1代码调用函数触发SIGBUS的可能原因分析
错误日志信息
Exception Type: EXC_BAD_ACCESS (SIGBUS) Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000280dc7da0 Exception Codes: 0x0000000000000002, 0x0000000280dc7da0 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: Namespace SIGNAL, Code 10 Bus error: 10 Terminating Process: exc handler [12171] VM Region Info: 0x280dc7da0 is in 0x280d50000-0x280dd0000; bytes after start: 490912 bytes before end: 33375 REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL VM_ALLOCATE 280cf0000-280d50000 [ 384K] rw-/rwx SM=ZER ---> VM_ALLOCATE 280d50000-280dd0000 [ 512K] rwx/rwx SM=ZER VM_ALLOCATE 280dd0000-280e50000 [ 512K] rw-/rwx SM=ZER
已知条件:
- 错误地址与函数地址一致
- 函数地址
0x280dc7da0对齐正常 - 目标内存区域拥有
rwx权限,具备可执行性 - Intel(x64)版本在x64 Mac及Rosetta环境下运行正常
可能的触发原因
1. ARM64指令集与调用约定不兼容
- 栈对齐要求未满足:ARM64强制要求函数调用前栈指针(SP)必须是16字节对齐。如果调用者代码未遵守这个规则,即使函数地址正确,执行时也会触发SIGBUS。而x64的栈对齐要求虽同为16字节,但Rosetta可能对非对齐情况做了兼容处理,或者Intel版本代码恰好符合对齐要求,因此未暴露问题。
- 无效指令编码:如果函数是动态生成(如JIT)或编译时生成了M1不支持的ARM指令(比如误用ARMv8.2+专属指令但编译选项未指定对应架构版本),即使地址对齐,CPU执行无效指令时也会抛出SIGBUS(部分无效编码会被归类为总线错误而非非法指令错误)。
2. 内存代码的可见性问题
- 缓存未同步:对于动态生成的代码(如JIT),写入内存后需要显式刷新缓存,确保CPU执行单元能读取到最新指令。M1的缓存架构与Intel不同,若未调用
__builtin___clear_cache这类函数刷新指令缓存,CPU可能读取到旧的无效数据(比如零页内容),导致执行时触发总线错误。 - 内存区域隐性损坏:虽然VM区域显示为
rwx,但该区域可能被其他代码越界写入破坏了函数指令。Intel架构的内存保护机制或Rosetta的兼容性处理可能掩盖了这种越界问题,而M1的内存检查更严格,直接触发错误。
3. 动态链接与符号解析异常
ARM64的动态链接机制(PLT/GOT结构)与x64存在差异:
- 符号重定向时指向了无效的代码位置,表面地址是函数地址,但实际内容并非正确指令。
- 动态链接器在M1上的行为与x64不同,导致函数入口的指令未被正确重定位。
4. 内存页的物理映射问题
VM_ALLOCATE分配的内存默认是零填充的虚拟页,若函数代码未被正确写入到该页(比如写入操作失败但未被检测到),CPU执行时会尝试读取未初始化的零页内容(全零在ARM64中是无效指令),进而触发SIGBUS。Intel架构或Rosetta可能对这种情况有不同的处理逻辑,未抛出错误。
内容的提问来源于stack exchange,提问作者Andromedary
相关产品推荐
相关产品推荐

