程序调用原子操作函数对结构体中的变量进行原子操作,程序coredump,堆栈如下:
Program received signal SIGBUS, Bus error. 0x000000000040083c in main () at /root/test/src/main.c:19 19 __sync_add_and_fetch(&a.count, step); (gdb) disassemble Dump of assembler code for function main: 0x0000000000400824 <+0>: sub sp, sp, #0x10 0x0000000000400828 <+4>: mov x0, #0x1 // #1 0x000000000040082c <+8>: str x0, [sp, #8] 0x0000000000400830 <+12>: adrp x0, 0x420000 <__libc_start_main@got.plt> 0x0000000000400834 <+16>: add x0, x0, #0x31 // 将变量的地址放入到x0寄存器 0x0000000000400838 <+20>: ldr x1, [sp, #8] // 指定ldxr取数据的长度(此处为8字节) => 0x000000000040083c <+24>: ldxr x2, [x0] // ldxr从x0寄存器指向的内存地址中取值 0x0000000000400840 <+28>: add x2, x2, x1 0x0000000000400844 <+32>: stlxr w3, x2, [x0] 0x0000000000400848 <+36>: cbnz w3, 0x40083c <main+24> 0x000000000040084c <+40>: dmb ish 0x0000000000400850 <+44>: mov w0, #0x0 // #0 0x0000000000400854 <+48>: add sp, sp, #0x10 0x0000000000400858 <+52>: ret End of assembler dump. (gdb) p /x $x0 $4 = 0x420039 // x0寄存器存放的变量地址不在8字节地址对齐处
ARM64平台对变量的原子操作、锁操作等用到了ldaxr、stlxr等指令,这些指令要求变量地址必须按变量长度对齐,否则执行指令会触发异常,导致程序coredump。
一般是因为代码中对结构体进行强制字节对齐,导致变量地址不在对齐位置上,对这些变量进行原子操作、锁操作等会触发问题。
如果结构体中变量会被作为原子操作、自旋锁、互斥锁、信号量、读写锁的输入参数,则需要修改代码保证这些变量按变量长度对齐。