如何在 GDB 中输出 HashMap 元素?

Posted

技术标签:

【中文标题】如何在 GDB 中输出 HashMap 元素?【英文标题】:How to output a HashMap element in GDB? 【发布时间】:2021-01-27 19:23:03 【问题描述】:

我只有一个二进制文件和一个核心转储,我需要在程序崩溃时使用 gdb 脚本返回 hashmap[8888][1] 中向量元素的值。在程序运行时,容器被损坏,但声称可以获得必要的数据。问题是如何使用指针或其他东西来到达所需的向量并取出我需要的元素?

(gdb) p hashmap
$1 = std::unordered_map with 5 elements
(gdb) ptype hashmap
type = std::unordered_map<int, std::vector<int>>
(gdb) p *(&hashmap - 2)
$2 = std::unordered_map with 94366596825088 elements = [88888] = std::vector of length 3, capacity 3 = 1706628932, 1495493257, 18800028, [8888] = std::vector of length 3, capacity 3 = 1254516933, 
    1257973910, 1938010846, [888] = std::vector of length 3, capacity 3 = 1976864792, 130725599, 41716398, [8] = std::vector of length 3, capacity 3 = 1533274456, 1112929722, 1834506749, 
  [88] = std::vector of length 3, capacity 3 = 1297327512, 118122261, 1973236149

【问题讨论】:

第一步通常是阅读std::unordered_map上的文档。 @tadman 我知道 unordered_map 是如何工作的,但是我没有任何迭代器或 gdb 中可用的任何其他函数,特别是我不能使用运算符 []。 > 据我所知,GDB 不能做你在代码中能做的所有事情。您可能需要存根更多调试代码并重新构建。 【参考方案1】:

通常,print hashmap 应该会产生您需要的所有输出。

例如编译这个程序:

#include <unordered_map>
#include <vector>

int main(int arch, char *argv[])

  std::unordered_map<int, std::vector<int>> hm;
  hm[7777].push_back(42);
  hm[7777].push_back(24);
  hm[8888].push_back(42);
  return 0;

并在 GDB 下运行它会导致:

(gdb) p hm
$1 = std::unordered_map with 2 elements = [8888] = std::vector of length 1, capacity 1 = 42, [7777] = std::vector of length 2, capacity 2 = 42, 24

我们可以在您的输出中看到 python 漂亮的打印机开始完成它的工作,但不知何故在句子中间失败了。

发生这种情况的原因有很多,从错误版本的 gccgdb,到错误安装的 libstdc++,等等。

您的问题缺少所有相关细节。

首先,您应该尝试复制上述程序的输出。如果可行,请提供 GCC、GDB、libstdc++ 的版本,我们可以进一步猜测。

更新:

容器轻微损坏

啊,这是标准漂亮打印机无法工作的另一个原因。

我想了解如何使用 gdb 脚本将其提取出来。

在内存损坏的情况下,您将不得不在原始内存中卑躬屈膝,没有捷径可走(甚至不能保证数据存在)。

您必须阅读并理解std::unordered_map 的实现细节。阅读它的漂亮打印机(通常安装到/usr/share/gdb/python/gdb/libstdcxx/v6/printers.py)会有所帮助。

【讨论】:

这是一个训练任务,其中标准容器略有损坏,显然这就是问题所在。 GCC、GDB、libstdc++ 完全正常工作。仍然纯粹是通过实验,我发现了这个: (gdb) p *(&hashmap - 2) $1 = std::unordered_map with 94366596825088 个元素 = [88888] = std::vector of length 3, capacity 3 = 1706628932, 1495493257, 18800028 , [8888] = std::vector of length 3, capacity 3 = 1254516933, 1257973910, 1938010846, ... 这意味着我的任务的答案是 1257973910,但我想了解如何将其拉出使用 gdb 脚本。

以上是关于如何在 GDB 中输出 HashMap 元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何在日志文件中包含GDB命令?

如何在 GDB 可以中断但不能算作函数的 GNU GAS ELF 输出中制作本地标签?

如何在交互式调试期间突出显示和着色 gdb 输出?

如何获取 gdb tui 程序集输出以显示指令?

Java之HashMap中如何删除指定元素(key)呢?

GDB:如何获取执行历史