2

最近在做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”,所以我必须对其进行动态转换,但 gdb 抱怨:

Error occurred in Python command: Couldn't determine value's most derived type for dynamic_cast

我已经花了几个小时,有经验的人能给我一些关于这个问题的提示,或者对我完成这个小工具有什么建议吗?我真的很感谢你的帮助,谢谢!

4

2 回答 2

1

如果没有更多信息,很难说出了什么问题。

GDB 正在尝试使用 RTTI 信息来查找该字段的完整对象。这在一段时间内失败了。您可以尝试通过使用“set print object on”从 CLI 重现问题,然后打印相关字段。

或者,您是否有特殊原因要使用 dynamic_cast?只需使用普通的“cast”方法。我认为这将绕过这些检查。

请注意,对于这种特定情况,您可能应该只选择现有的 libstdc++ 漂亮打印机。它们与 gdb 中现有的“打印”命令集成,并且已经处理了 libstdc++ 中的每个复杂数据结构。许多发行版以在您的程序使用 libstdc++ 时自动启用它的方式提供所有这些代码。

于 2013-05-24T17:02:49.083 回答
0

我也从dynamic_cast()看到了同样的错误。使用cast()而不是dynamic_cast()可以工作:

列表漂亮打印.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;
}

列表漂亮的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.
于 2013-05-24T17:22:43.063 回答