c - 在调用栈中,当typepointer的参数持有模式0x8080808080808080或0xf8f8f8f8f8f8f8f8的地址时,表示什么?

标签 c debugging gdb

当我使用 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 Aregister 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/

相关文章:

c - 并行运行两个程序,每个程序都有无限循环

javascript - 在 Chrome 中将对象记录到控制台的解决方法

node.js - 使用 VSCode 调试器找不到 Node 进程

debugging - 在 gdb 中的 errno 上设置观察点

内置 qsort 函数中的比较函数

c - 有没有办法包装具有 va_args 参数的函数?

c++ - int64_t 的定义

.net - 编写.NET互操作调试器

c - 在 gdb 上,LoadLibrary 满足 sti 指令并发出 SIGILL 信号

GDB 重置 LD_LIBRARY_PATH