LINUX.ORG.RU

GDB Python, проинспектировать std::vector

 , ,


1

5

Привет,

Я снова с GDB. Теперь пытаюсь написать GDB command корорая мне напечатает вектор как нужно. Но почему-то не могу из gdb.Value (std::vector<Foo>) добраться ни до размера вектора ни до его данных.

Т.е. есть приблизительно такой код:

struct Foo { 
    int a; 
    explicit Foo(in a) : a(a) {}
};

int main() {
    std::vector<Foo*> v = { new Foo(1), new Foo(2), new Foo(3) };
    return 0;
}

Сейчас я печатаю вектор в такой способ:

def FooVect (gdb.Command):
  def __init__(self):
    super(FooVect, self).__init__('foovect', gdb.COMMAND_OBSCURE, gdb.COMPLETE_SYMBOL)

  def invoke(self, arg, from_tty):
    size = gdb.parse_and_eval('({0}).size()'.format(arg))
    for i in range(0, size):
      print '[{0}] {1}'.format(i, gdb.parse_and_eval('({0})[{1}].a'.format(i, arg)))

Потом в gdb:

(gdb) foovect v
[0] 1
[1] 2
[2] 3

Однако parse_and_eval довольно медленный и когда количество итемов растет, приходится долго ждать. Насколько я понимаю parse_and_eval «вытягивает» целый символ с вместе потрохами. Т.е. можно было бы обойтись одним вызовом parse_and_eval.

Но если код invoke (например) сделать таким:

  v = gdb.parse_and_eval(arg)
  print v[0]

То ничего не получается:

Traceback (most recent call last):
  File "<string>", line 2, in <module>
gdb.error: Cannot subscript requested type.
Error while executing Python code.

Более того: в через v вообще не видно как достаться до данных вектора:

(gdb) python
>v = gdb.parse_and_eval('v')
>print dir(v)
>end
['__abs__', '__add__', '__and__', '__call__', '__class__', '__delattr__', '__delitem__', '__div__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__int__', '__invert__', '__le__', '__len__', '__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rxor__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'address', 'cast', 'const_value', 'dereference', 'dynamic_cast', 'dynamic_type', 'fetch_lazy', 'is_lazy', 'is_optimized_out', 'lazy_string', 'reference_value', 'referenced_value', 'reinterpret_cast', 'string', 'type']

Есть идеи? Может системные pretty-printers для std::vector мешают?

(gdb) python
>v = gdb.parse_and_eval('combinedPUPaths')
>print v
>end
std::vector of length 3, capacity 4 = {
  0x7f3edd4d66f0,
  0x7f3edd4d6710,
  0x7f3edd4d6720
}

P.S.

$ cat ~/.gdbinit
set print array on
set print pretty on
set print object on
set print static-members off

gdb предоставляет доступ к своим внутренностям и виденью данных программы, а не к возможностям по интерпретации C++. Как я понимаю, надо вручную делать индексацию (1 это к указателю прибавляется для доступа ко второму элементу вектора):

python print (gdb.parse_and_eval('v')['_M_impl']['_M_start'] + 1).dereference()

xaizek ★★★★★ ()
Ответ на: комментарий от xaizek

Чесно признать, конкретно это я не пробовал. Но v['_M_size'] не работал. Викидывало ровно такую же ошибку.

Спасибо, попробую, как доберусь до компьютера.

KennyMinigun ★★★★★ ()

Ну в цепепе отладка - дело трудоёмкое :-) Пробираться через тонны смарт-поинтеров, через RAII над RAII над смарт-поинтерами быстро утомляет так, что даже скрипт на питоне тормозит :-) Лол :-)

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.