Не удалось определить наиболее производный тип значения для dynamic_cast

Недавно я работаю над расширением Python gdb7, я просто хочу использовать его для написания небольшого инструмента для отображения содержимого контейнеров C ++ (например, списка), дружественных при отладке. Но у меня возникли проблемы при работе со списком. Это мой код 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;
}

И я пишу небольшой код на Python после учебника «Отладка с помощью gdb», просто пытаюсь отобразить содержимое 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

Я потратил на это несколько часов, может кто-нибудь опытный предложить мне несколько советов об этой проблеме или какие-нибудь предложения для меня, чтобы выполнить этот маленький инструмент? Я очень ценю вашу помощь, спасибо!

2

Решение

Трудно сказать, что пошло не так без дополнительной информации.

GDB пытается использовать информацию RTTI, чтобы найти полный объект для этого поля. Это терпит неудачу в течение некоторого времени. Вы можете попытаться воспроизвести проблему из интерфейса командной строки, используя команду «установить объект печати», а затем распечатать соответствующее поле.

В качестве альтернативы, есть ли конкретная причина, по которой вы хотите использовать dynamic_cast? Просто используйте вместо этого простой метод «cast». Я думаю, что обойдут эти проверки.

Обратите внимание, что для этого конкретного случая вам, вероятно, следует просто подобрать существующие libstdc ++ pretty-printers. Они интегрируются с существующей командой «print» в gdb и уже обрабатывают все сложные структуры данных в libstdc ++. Многие дистрибутивы поставляют весь этот код так, чтобы он автоматически включался, когда ваша программа использует libstdc ++.

1

Другие решения

Я вижу ту же ошибку от dynamic_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.
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector