在使用gdb
调试分段错误时,我得到了这种非常奇怪的行为:
(gdb) select 4
(gdb) p mrb
$3 = (mrb_state *) 0x555555dcc000
(gdb) p mrb->eStandardError_class
$4 = (RClass *) 0x0
(gdb) select 3
(gdb) p mrb
$6 = (mrb_state *) 0x555555dcc000
(gdb) p mrb->eStandardError_class
$7 = (struct RClass *) 0x555556015190
我不明白,因为在这两种情况下mrb
变量指向内存中的同一位置0x555555dcc000
,但在一种情况下mrb->eStandardError_class
为空,而在另一种情况下,它有一个有意义的价值。
这怎么可能?这是gdb
错误吗?编译器错误?或者这是不正常的? mrb->eStandardError_class
可以是一个堆栈帧中的寄存器还是另一个堆栈帧中的内存值?
为了更清楚:我在p mrb->eStandardError_class
的两次调用之间没有运行任何代码。所以我不希望改变这个价值。它如何依赖于帧?
编辑,我有:
(gdb) p &(((mrb_state *)0)->eStandardError_class)
$8 = (struct RClass **) 0x170
(gdb) select 4
(gdb) p &(((mrb_state *)0)->eStandardError_class)
$9 = (RClass **) 0x160
所以看起来这两个单元没有使用相同的选项进行编译。
答案 0 :(得分:3)
(从评论中移出)
如果两个堆栈帧位于不同的转换单元中,则可执行文件可能来自拙劣的编译,其中两个TU看到mrb_state
/ RClass
的不同定义。这通常在struct
/ class
的定义发生更改时发生,但并非所有使用它的模块都会重新编译。在这种情况下,特别有可能的是,gdb在一个堆栈帧中讨论RClass *
而在另一个堆栈帧中讨论struct RClass *
- 这可能暗示它正在讨论不同的类型。
您可以通过执行
快速检查是否是这种情况p &(((mrb_state *)0)->eStandardError_class)
在两个堆栈帧中 - 如果该成员的偏移量不同,则确认两个TU对mrb_state
的含义有不同的看法。