当我使用 GDB 调试问题时,我遇到了这种奇怪的行为。我无法用任何合乎逻辑的答案说服自己。
下面是由于函数开头的断点而获得的调用堆栈的快照(为了简单起见,我将堆栈帧限制为 3 级)。
(gdb)
#0 hashset_get (hashset=<value optimized out>, item_key=0x7fffd7e4f5b8)
at /xxx/yyy/zzz/hashset.c:123
#1 0x00007fffed855d00 in hashmap_get (hashmap=<value optimized out>, key=0x7fffd7e4f648)
at /xxx/yyy/zzz/hashmap.c:789
#2 0x00007ffa589d8eeb in hashmap_get_value (hashmap=0x7ff9d82d1b78, key=0x7fffd7e4f648)
at /xxx/yyy/zzz/hashmap.c:456
在此之后有一个单步执行。后来哪个堆栈帧看起来如下-
(gdb) bt
#0 hashset_get (hashset=0xf8f8f8f8f8f8f8f8, item_key=0x7fffd7e4f5b8)
at /xxx/yyy/zzz/hashset.c:125
#1 0x00007fffed855d00 in hashmap_get (hashmap=<value optimized out>, key=0x7fffd7e4f648)
at /xxx/yyy/zzz/hashmap.c:789
#2 0x00007ffa589d8eeb in hashmap_get_value (hashmap=0x7ff9d82d1b78, key=0x7fffd7e4f648)
at /xxx/yyy/zzz/hashmap.c:456
我知道当 GDB 将任何变量显示为“值优化输出”时,它表示它的值存储在寄存器中而不是存储在堆栈帧中。
但是,在这种情况下,最初显示为“值优化输出”的 arg
hashset
后来更改为某个地址位置 - 0xf8f8f8f8f8f8f8f8
。那么这是否意味着它最初将 hashset
存储在寄存器中然后在堆栈帧上创建了一个空间? 而且这个地址看起来不像任何其他内存位置地址。您可以在地址中看到一些模式(例如 f8f8...)
更令人困惑的是,如果我尝试在该位置打印数据,GDB 输出如下-
(gdb) p *hashset
Cannot access memory at address 0xf8f8f8f8f8f8f8f8
我尝试了一些更多的东西,希望它可以帮助理解这种行为。
我为
0x7fffd7e4f5b8
分配了一个有效地址 item_key
- 它由 arg hashset
持有(gdb) s hashset=0x7fffd7e4f5b8
(gdb) p *hashset
Cannot access memory at address 0xb8b8b8b8b8b8b8b8
(gdb) p hashset
$6 = (hashset) 0xb8b8b8b8b8b8b8b8
但令我惊讶的是,当我打印
hashset
的值时,它显示的地址是 0xb8b8b8b8b8b8b8b8
而不是 0x7fffd7e4f5b8
! 有人可以解释一下这里发生了什么吗?
[编辑:没有崩溃/挂起。系统正常运行]
最佳答案
I know that when the GDB shows any variable as "value optimized out", it indicates that its value is stored in register instead of storing on the stack frame.
这不是“值(value)优化”的意思。
这意味着:编译器没有在当前程序计数器上提供这个变量的位置信息。
理论上,
DWARF
标准足够丰富,它可以描述诸如“可以通过将 constant
添加到 register
的值来定位此变量”,或“通过添加 register A
和 register B
并将结果与 contents of location pointed by register C
进行或运算”这样的内容。在实践中,很少有编译器达到这样的长度,而是简单地省略信息。However, in this case, the arg hashset which was initially shown as "value optimized out" is later changed to some address location
当您推进程序计数器时,GDB 在新 PC 上找到位置信息。但是解释该位置信息会产生值
0xf8f8f8f8f8f8f8f8
,它不能是 x86_64
上的指针的真值.由此您可以得出结论,要么位置信息不正确(编译器错误;很可能),要么 GDB 没有正确解释
DWARF
描述(并非闻所未闻)。不幸的是,在调试优化的代码时,这种调试工件是生活中的事实。它们还依赖于 GCC 和 GDB 的确切版本——新版本通常(但不总是!)更好。 Clang/LLVM 目前非常糟糕,并且产生“值(value)优化”的频率比它应该的要高得多。
关于c - 在调用栈中,当typepointer的参数持有模式0x8080808080808080或0xf8f8f8f8f8f8f8f8的地址时,表示什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52280153/