最近我正在研究gdb7的python扩展,我只是想用它来编写一个小工具,在调试时显示C ++容器(如list)的内容友好。但是在处理list时遇到了麻烦。这是我用于测试的C ++代码:
int main() {
list<int> int_lst;
for (int i = 0; i < 10; ++i)
int_lst.push_back(i);
for(list<int>::const_iterator citer = int_lst.begin();
citer != int_lst.end(); ++citer)
cout << *citer << " ";
cout << endl;
return 0;
}
我在'使用gdb调试'教程之后写了一个小的python代码,试着显示int_lst的内容
import gdb
class Hello(gdb.Command):
def __init__(self):
super(Hello, self).__init__("plist", gdb.COMMAND_OBSCURE)
def invoke(self, arg, from_tty):
cpp_lst = gdb.parse_and_eval("int_lst")
header = cpp_lst['_M_impl']['_M_node']
next = header['_M_next']
# next is _List_node_base, I have to cast it to its derived type for data
next.dynamic_cast(gdb.lookup_type("std::_List_node<``int>").pointer())
Hello()
在C ++ STL中,std :: _ List_node_base是列表中节点的基类,但只有派生模板类std :: _ List_node具有包含该值的数据成员“_M_data”,所以我必须对它进行dynamic_cast,但是gdb抱怨:
Error occurred in Python command: Couldn't determine value's most derived type for dynamic_cast
我花了几个小时的时间,有没有经验的人能给我一些关于这个问题的提示,或者对我来说有什么建议来完成这个小工具?非常感谢你的帮助,谢谢!
答案 0 :(得分:1)
如果没有更多信息,很难说出了什么问题。
GDB正在尝试使用RTTI信息来查找该字段的完整对象。这是一个简单的失败。您可以尝试使用“set print object on”从CLI重现问题,然后打印相关字段。
或者,您是否有特殊原因要使用dynamic_cast?只需使用简单的“强制转换”方法。我认为这将绕过这些检查。
请注意,对于这种特定情况,您可能应该选择现有的libstdc ++ pretty-printers。它们与gdb中现有的“print”命令集成,并且已经处理了libstdc ++中的每个复杂数据结构。许多发行版都以一种在程序使用libstdc ++时自动启用它的方式发布所有代码。
答案 1 :(得分:0)
我也从 dynamic_cast()中看到同样的错误。使用 cast()代替 dynamic_cast()可以:
<强> list-pretty-print.cc 强>
#include <iostream>
#include <list>
/* https://github.com/scottt/debugbreak */
#include "debugbreak/debugbreak.h"
using namespace std;
int main()
{
list<int> int_lst;
debug_break();
for (int i = 0; i < 10; ++i)
int_lst.push_back(i);
debug_break();
for(list<int>::const_iterator citer = int_lst.begin();
citer != int_lst.end(); ++citer)
cout << *citer << " ";
cout << endl;
return 0;
}
<强> list-pretty-print.py 强>
import gdb
class PList(gdb.Command):
def __init__(self):
super(PList, self).__init__('plist', gdb.COMMAND_OBSCURE)
def invoke(self, arg, from_tty):
int_list_pointer_type = gdb.lookup_type('std::_List_node<int>').pointer()
lst = gdb.parse_and_eval('int_lst')
node = lst['_M_impl']['_M_node']
nxt = node['_M_next']
if node.address == nxt:
gdb.write('{}\n')
return
else:
gdb.write('{')
while True:
e = nxt.cast(int_list_pointer_type).dereference()
gdb.write('%d, ' % (e['_M_data'],))
nxt = e['_M_next']
if node.address == nxt:
gdb.write('}\n')
return
PList()
<强>测试一览漂亮-print.gdb 强>
set confirm off
set pagination off
set python print-stack full
file list-pretty-print
source list-pretty-print.py
run
up 2
plist
continue
up 2
plist
quit
示例会话
$ gdb -q -x test-list-pretty-print.gdb
Program received signal SIGTRAP, Trace/breakpoint trap.
trap_instruction () at list-pretty-print.cc:15
15 for (int i = 0; i < 10; ++i)
#2 main () at list-pretty-print.cc:13
13 debug_break();
{}
Program received signal SIGTRAP, Trace/breakpoint trap.
trap_instruction () at list-pretty-print.cc:20
20 for(list<int>::const_iterator citer = int_lst.begin();
#2 main () at list-pretty-print.cc:18
18 debug_break();
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, }
看一下表达链,我不确定 dynamic_cast()应该在那里工作:
(gdb) whatis int_lst
type = std::list<int, std::allocator<int> >
(gdb) whatis int_lst._M_impl
type = std::_List_base<int, std::allocator<int> >::_List_impl
(gdb) whatis int_lst._M_impl._M_node._M_next
type = std::__detail::_List_node_base *
(gdb) python print gdb.parse_and_eval('int_lst._M_impl._M_node._M_next').dynamic_type
std::__detail::_List_node_base *
(gdb) python print gdb.parse_and_eval('int_lst._M_impl._M_node._M_next').dynamic_cast(gdb.lookup_type('std::_List_node<int>').pointer())
Traceback (most recent call last):
File "<string>", line 1, in <module>
gdb.error: Couldn't determine value's most derived type for dynamic_cast
Error while executing Python code.