【发布时间】:2011-06-09 21:13:32
【问题描述】:
我一生中见过很多核心转储,但这一次让我难过。
上下文:
- 在AMD Barcelona CPU 集群上运行的多线程 Linux/x86_64 程序
- 崩溃的代码被执行了很多
- 在负载下运行 1000 个程序实例(完全相同的优化二进制文件)每小时会产生 1-2 次崩溃
- 崩溃发生在不同的机器上(但机器本身非常相似)
- 崩溃看起来都一样(相同的确切地址,相同的调用堆栈)
以下是崩溃的详细信息:
Program terminated with signal 11, Segmentation fault.
#0 0x00000000017bd9fd in Foo()
(gdb) x/i $pc
=> 0x17bd9fd <_Z3Foov+349>: rex.RB orb $0x8d,(%r15)
(gdb) x/6i $pc-12
0x17bd9f1 <_Z3Foov+337>: mov (%rbx),%eax
0x17bd9f3 <_Z3Foov+339>: mov %rbx,%rdi
0x17bd9f6 <_Z3Foov+342>: callq *0x70(%rax)
0x17bd9f9 <_Z3Foov+345>: cmp %eax,%r12d
0x17bd9fc <_Z3Foov+348>: mov %eax,-0x80(%rbp)
0x17bd9ff <_Z3Foov+351>: jge 0x17bd97e <_Z3Foov+222>
您会注意到崩溃发生在0x17bd9fc 的指令中间,这是在从0x17bd9f6 的调用返回到虚函数之后。
当我检查虚拟表时,我发现它没有以任何方式损坏:
(gdb) x/a $rbx
0x2ab094951f80: 0x3f8c550 <_ZTI4Foo1+16>
(gdb) x/a 0x3f8c550+0x70
0x3f8c5c0 <_ZTI4Foo1+128>: 0x2d3d7b0 <_ZN4Foo13GetEv>
并且它指向这个微不足道的函数(正如通过查看源代码所预期的那样):
(gdb) disas 0x2d3d7b0
Dump of assembler code for function _ZN4Foo13GetEv:
0x0000000002d3d7b0 <+0>: push %rbp
0x0000000002d3d7b1 <+1>: mov 0x70(%rdi),%eax
0x0000000002d3d7b4 <+4>: mov %rsp,%rbp
0x0000000002d3d7b7 <+7>: leaveq
0x0000000002d3d7b8 <+8>: retq
End of assembler dump.
此外,当我查看Foo1::Get() 应该返回的返回地址时:
(gdb) x/a $rsp-8
0x2afa55602048: 0x17bd9f9 <_Z3Foov+345>
我看到它指向了正确的指令,所以好像在从Foo1::Get() 返回期间,出现了一些 gremlin,并将 %rip 增加了 4。
合理的解释?
【问题讨论】:
-
你有没有发现是什么原因造成的?如果是这样,我很想知道它是什么!
-
@us2012 我相信我们确实找到了原因。看我的回答。
标签: linux segmentation-fault x86-64