使用gdb检查标准容器(std :: map)内容


93

假设有这样的事情:

#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

有没有办法做到这一点?

Answers:


35

我认为没有,至少没有,如果您的源代码经过优化等。但是,有一些gdb宏可以为您检查STL容器:

http://sourceware.org/ml/gdb/2008-02/msg00064.html

但是,我不使用它,所以YMMV


1
感谢您的链接;唯一的事情是宏依赖于stl库版本,我希望避免使用它。+1
Paolo Tedesco,

诸如“ plist foo std :: string”之类的命令给出语法错误也令人沮丧。看来value_type不能包含任何标点符号。
Bklyn

2
我没有尝试过,但是如果它与GDB的其余部分一样工作,则可以在名称中使用标点符号将其括在单引号中。
jpalecek,2009年

2
注意:这些脚本中的std :: map功能假定32位指针类型。对于64位计算机,将文件中的“ + 4”替换为“ + 8”。
凯尔·西梅克

我的gdb中没有定义pvector(版本7.5.91.20130417-cvs-ubuntu)。
杰夫

91

现有的这个问题的答案是非常不合时宜的。借助最新的GCC和GDB,Just Works TM得益于GDB 7.x中内置的Python支持以及GCC随附的libstdc ++漂亮打印机。

对于OP的示例,我得到:

(gdb) print m
$1 = std::map with 2 elements = {[1] = 2, [2] = 4}

如果它不能自动运行,请参阅GDB Wiki 的STL支持页面上的第一个项目符号。

您也可以为自己的类型编写Python漂亮打印机,请参阅GDB手册中的漂亮打印


2
是的,但是其他问题作为重复的问题正在解决,所以我希望它具有最新的信息。
乔纳森·威克利

1
我正在使用GDB 7.2,并且上面的作品...如果您的收藏很小。除了诉诸于使用STL实现的内部结构之外,我还没有找到任何方法来从4K向量中打印说元素1543。
pavon,

5
是的,在GDB 7.2和icpc编译器中,出现错误Could not find operator[]
pavon,

11
不幸的是,它并非在所有发行版中都“正常工作”。在Ubuntu 13.10中,默认情况下未安装该工具,尝试手动安装时
nietaki

1
@ razeh,Fedora,RHEL(和RHEL克隆)。有一个正在解决的问题,使打印机也可以在将GDB链接到Python 3的发行版上工作
Jonathan Wakely 2014年

25

总有一个明显的发现:定义自己的测试功能...从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) 

16
只要进程正在运行。对于核心转储不是那么有用。
肖恩·莱利,2009年

2
通常,这不仅对STL有用,还是对GDB调试有用的建议。我保留了一个完整的gdb帮助器函数库,用于处理许多难以检索的数据,例如write_cuda_array_as_image()。请注意,有些编译器会删除所有未调用的函数,因此我在主函数的“ return 0;”之后放置对每个帮助器函数的调用。另外,使用extern“ C”声明它们使从gdb调用它们更加容易。
凯尔·西梅克

21

stl-views.gdb曾经是最好的答案出现了,但现在不是了。

这还没有集成到主线中GDB,但是这是使用'archer-tromey-python' 分支得到的结果

(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


1

上面的答案是行之有效的。如果您使用的是stl-views.gdb,这是查看其中的地图和元素的正确方法。让您的地图如下: std::map<char, int> myMap;

(gdb) pmap myMap char int

pmap <variable_name> <left_element_type> <right_element_type>查看地图中的元素。

希望能有所帮助。


0

您可以Cannot evaluate function -- may be inlined通过确保编译器在编译程序时使用DWARF-2(或3或4)调试信息来解决第二个问题()。DWARF-2包含内联信息,因此您应该能够使用所描述的任何一种方法来访问std::map容器的元素。

要使用DWARF-2调试信息-gdwarf-2进行编译,请将标志添加到您的compile命令中。


1
嗯,知道在哪里内联了一个函数,这使得GDB无法评估对该函数的调用。GDB确实需要访问该函数的离线副本!
SamB 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.