如果a具有相同的值,a-> b如何依赖于所选的堆栈帧?

时间:2017-09-24 09:16:02

标签: c++ gdb

在使用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的两次调用之间没有运行任何代码。所以我不希望改变这个价值。它如何依赖于帧?

按照Matteo Italia的建议

编辑,我有:

(gdb) p &(((mrb_state *)0)->eStandardError_class)
$8 = (struct RClass **) 0x170
(gdb) select 4
(gdb) p &(((mrb_state *)0)->eStandardError_class)
$9 = (RClass **) 0x160

所以看起来这两个单元没有使用相同的选项进行编译。

1 个答案:

答案 0 :(得分:3)

(从评论中移出)

如果两个堆栈帧位于不同的转换单元中,则可执行文件可能来自拙劣的编译,其中两个TU看到mrb_state / RClass的不同定义。这通常在struct / class的定义发生更改时发生,但并非所有使用它的模块都会重新编译。在这种情况下,特别有可能的是,gdb在一个堆栈帧中讨论RClass *而在另一个堆栈帧中讨论struct RClass * - 这可能暗示它正在讨论不同的类型。

您可以通过执行

快速检查是否是这种情况
p &(((mrb_state *)0)->eStandardError_class)

在两个堆栈帧中 - 如果该成员的偏移量不同,则确认两个TU对mrb_state的含义有不同的看法。