使用 gdb 检查标准容器 (std::map) 内容
Posted
技术标签:
【中文标题】使用 gdb 检查标准容器 (std::map) 内容【英文标题】:Inspecting standard container (std::map) contents with gdb 【发布时间】:2010-09-30 11:11:52 【问题描述】:假设有这样的东西:
#include <map>
int main()
std::map<int,int> m;
m[1] = 2;
m[2] = 4;
return 0;
我希望能够检查从 gdb 运行程序的地图内容。 如果我尝试使用下标运算符,我会得到:
(gdb) p m[1]
Attempt to take address of value not located in memory.
使用 find 方法不会产生更好的结果:
(gdb) p m.find(1)
Cannot evaluate function -- may be inlined
有没有办法做到这一点?
【问题讨论】:
打印所有元素而不截断大地图:***.com/questions/47743215/… 更多“无法评估函数可能内联”的重点:***.com/questions/40633787/… 一般问题:c++ - How to pretty-print STL containers in GDB? - Stack Overflow 【参考方案1】:此问题的现有答案非常已过时。由于 GDB 7.x 中内置的 Python 支持以及 GCC 附带的 libstdc++ 漂亮的打印机,它使用最近的 GCC 和 GDB 即可工作TM。
对于 OP 的示例,我得到:
(gdb) print m
$1 = std::map with 2 elements = [1] = 2, [2] = 4
如果它不能自动运行,请查看 GDB wiki 的 STL Support 页面上的第一个要点。
您也可以为自己的类型编写 Python 漂亮的打印机,请参阅 GDB 手册中的 Pretty Printing。
【讨论】:
是的,但是其他问题作为重复的问题正在关闭,所以我希望它有最近的信息。 我正在使用 GDB 7.2 并且上面的作品......如果你有一个小集合。除了使用 STL 实现的内部结构外,我还没有找到任何方法从 4K 矢量打印元素 1543。 是的,在 GDB 7.2 和 icpc 编译器中我收到错误Could not find operator[]
。
不幸的是,它并不是在所有发行版中都“正常工作”。在 Ubuntu 13.10 中默认没有安装它,并且有 problems when you try to install it manually
@razeh、Fedora、RHEL(和 RHEL 克隆)。正在进行修复以使打印机也可以在 GDB 链接到 Python 3 的发行版上运行【参考方案2】:
我认为没有,至少在您的源代码经过优化等情况下不会。但是,gdb 有一些宏可以为您检查 STL 容器:
http://sourceware.org/ml/gdb/2008-02/msg00064.html
不过我不用这个,所以YMMV
【讨论】:
感谢您的链接;唯一的问题是宏依赖于 stl 库版本,我希望避免这种情况。 +1 像“plist foo std::string”这样的命令给出语法错误也有点令人沮丧。看来 value_type 不能包含任何标点符号。 我没试过,但如果这和 GDB 的其他部分一样,用单引号将带标点名称的名称括起来就可以了。 注意:这些脚本中的 std::map 功能假定为 32 位指针类型。对于 64 位机器,将文件中的“+ 4”替换为“+ 8”。 pvector 未在我的 gdb(版本 7.5.91.20130417-cvs-ubuntu)中定义。【参考方案3】:总是很明显:定义您自己的测试函数...从 gdb 调用它。例如:
#define SHOW(X) cout << # X " = " << (X) << endl
void testPrint( map<int,int> & m, int i )
SHOW( m[i] );
SHOW( m.find(i)->first );
int
main()
std::map<int,int> m;
m[1] = 2;
m[2] = 4;
return 0; // Line 15.
还有:
....
Breakpoint 1 at 0x400e08: file foo.C, line 15.
(gdb) run
Starting program: /tmp/z/qD
Breakpoint 1, main () at qD.C:15
(gdb) call testPrint( m, 2)
m[i] = 4
(*m.find(i)).first = 2
(gdb)
【讨论】:
只要进程正在运行。对于核心转储不是那么有用。 这是一个有用的建议,一般调试 GDB,而不仅仅是使用 STL。我为大量难以检索的数据保留了一个完整的 gdb 辅助函数库,例如write_cuda_array_as_image()。请注意,某些编译器会删除任何未调用的函数,因此我在 main 的“return 0;”之后调用每个辅助函数。还用 extern "C" 声明它们使得从 gdb 调用它们更容易。 @KyleSimek gcc 还支持` __attribute__((used))`,因此如果未使用,链接器不会丢弃符号【参考方案4】:stl-views.gdb
曾经是最好的答案,但现在不是了。
这还没有集成到主线 GDB
中,但这是使用“archer-tromey-python”branch 得到的结果:
(gdb) list
1 #include <map>
2 int main()
3 std::map<int,int> m;
4 m[1] = 2;
5 m[2] = 4;
6 return 0;
7
(gdb) break 6
Breakpoint 1 at 0x8048274: file map.cc, line 6.
(gdb) run
Breakpoint 1, main () at map.cc:6
6 return 0;
(gdb) print m
$1 = std::map with 2 elements =
[1] = 2,
[2] = 4
(gdb) quit
【讨论】:
【参考方案5】:尝试取消引用 STL 容器:在此页面上:http://www.yolinux.com/TUTORIALS/GDB-Commands.html
【讨论】:
这些看起来是生意! 它们实际上与上一个答案中的宏相同 :) 恐怕没有更简单的解决方案了。 命令是什么?你设法用大量不相关的信息在场外运行我们。我对“如何启动 GDB”和其他内容不感兴趣。【参考方案6】:上面的答案很好用。如果您使用的是 stl-views.gdb,这是查看其中的地图和元素的正确方法。
让你的地图如下:
std::map<char, int> myMap;
(gdb) pmap myMap char int
即pmap <variable_name> <left_element_type> <right_element_type>
查看地图中的元素。
希望对您有所帮助。
【讨论】:
【参考方案7】:您可以通过确保您的编译器在编译程序时使用 DWARF-2(或 3 或 4)调试信息来解决第二个问题 (Cannot evaluate function -- may be inlined
)。 DWARF-2 包含内联信息,因此您应该能够使用您描述的任何一种方法来访问 std::map
容器的元素。
要使用 DWARF-2 调试信息进行编译,请将 -gdwarf-2
标志添加到您的编译命令中。
【讨论】:
嗯,知道一个函数被内联的位置并不能让 GDB 评估对该函数的调用; GDB 确实需要访问该函数的离线副本!以上是关于使用 gdb 检查标准容器 (std::map) 内容的主要内容,如果未能解决你的问题,请参考以下文章