我们有一个运行在Linux 2.6.32上的posix多线程c++程序,它在其中一个线程中进行内核转储。使用gdb-7.2交叉编译分析核心文件,我们看到错误指令在这里
0x11491178 <+208>: lwz r0,8(r9)
和寄存器在帧中显示:
(gdb) info reg
r0 0x0 0
….
r9 0xdeaddead 3735936685
这是有意义的,因为r9在进程/线程上下文中有一个无效的地址值(实际上是我们写的堆擦洗模式)。
令人困惑的是r9是这样加载的
0x1149116c <+196>: lwz r9,0(r4)
和r4包含(第一个也是唯一一个)函数参数"data"的值。GDB告诉我以下关于数据的信息:
(gdb) p data
$6 = (TextProcessorIF *) 0x4b3fe858
(gdb) p *data
$7 = {_vptr.TextProcessorIF = 0x128b5390}
(gdb) info symbol 0x128b5390
vtable for TextProcessorT<unsigned short> + 8 in section .rodata
在这个上下文中都是正确的。所以r9的值应该是0x128b5390,而不是模式"0xdeaddead",这是在内存被释放并返回堆时写入的。
那么,为什么当内存中包含合法对象时,寄存器r9包含擦除值。我的理论是,内核包含内存的快照,就像进程死亡时,这是在实际崩溃发生时更进一步的线。在SIGSEGV被触发之后,堆内存的这个位置仍然可以被其他线程使用,因为它们正在记录数据,直到时间进程结束。因此,数据所指向的内存可能已经被重新分配,并且在内存快照被拍摄并保存在内核中时正在使用/被使用。
我的问题是:A)我的理论正确吗?
B)我是否正确地假设堆内存快照不是在崩溃时拍摄的(信号被提出),而是在进程的最后时刻?
C)地址/位置导致SIGSEGV仍然可以使用(由其他线程)?
谢谢!
您是否使用SIGSEGV
的信号处理程序?它们是异步的和可重入的吗?
参见如何编写一个信号处理程序来捕获SIGSEGV?