GDB pretty-printer: печать массива, когда размер известен родительской структуре
У меня есть структура в C++ что-то вроде этого:
struct HeapBlock {
char* data;
}
struct DataBlock {
int size;
HeapBlock hb;
}
Они являются частью структуры и имеют несколько других членов, помощников и так далее, но это важные части. Я хотел бы показать это на симпатичном принтере Python GDB примерно так:
NAME TYPE VALUE
DataBlock: DataBlock "Size 2000 @ 0x445343"
|--->size int 2000
|--->data HeapBlock {...}
|--->[0] char 0x34
|--->[1] char 0x45
....
<more values>
До сих пор мне не удалось показать HeapBlock как отдельный дочерний элемент. Я успешно использовал итератор для создания:
NAME TYPE VALUE
DataBlock: DataBlock
|--->size int 2000
|--->[0] char 0x34
|--->[1] char 0x45
....
<more values>
Это было сделано путем возврата db["size"]
в первом результате от итератора, возвращенного DataBlockPrinter
"s children()
метод, а затем из db["hb"]["data"]
для следующего size
Результаты.
Я также пытался использовать отдельный принтер для HeapBlocks
Но проблема в том, что HeapBlock
понятия не имеет, насколько он велик: что хранится в родительском (DataBlock
), Итак HeapBlock
принтер также не знает, когда прекратить итерации.
Можно ли получить size
поле к HeapBlock
красивый принтер, когда он печатается как часть DataBlock
Вот?
2 ответа
Я нашел другой способ
#convert to vector
class DataBlock:
def iter(self):
p=self.v['p']
emtp=p.type.target().unqualified().strip_typedefs()
pv=emtp.vector(self.cnt-1).pointer()#convert to vector,the actual type is char (*) __attribute__ (vector_size(self.cnt)))
yield('p',p.cast(pv))
#We register this type
def regCls(v):
if str(v.type).find(") __attribute__ ((vector_size")>0:
return _py_vector(v)
def regMyPP():gdb.pretty_printers.append(regCls)
#Then parse this type out
class _py_vector:
def __init__(self,v):self.v=v
def tp(self):
s=str(self.v.type)
return gdb.lookup_type(s[:s.find('(')-1]).pointer()#eg.char
def sz(self):
s=str(self.v.type)
st=s.find('vector_size(')+12
ed=s.find(')',st)
return int(s[st:ed])#Get it's size
def to_string(self): return self.v.cast(self.tp()).lazy_string(length=self.sz())
def display_hint(self): return 'string'
К сожалению, нет встроенного способа сделать это. Я считаю, что в gdb bugzilla есть открытая ошибка.
Это может быть возможно сделать с помощью взлома: в DataBlock
принтер, запишите адрес и размер HeapBlock
в хеш-таблице. Тогда HeapBlock
Принтер может посмотреть это. Конечно, тогда возникает проблема с решением о том, как сделать кэш недействительным. Не совсем удачно придумать хороший способ:-(Но, может быть, это нормально - просто не лишать его законной силы. Вы можете попробовать сделать его недействительным, когда DataBlock
принтер уничтожен; GDB не гарантирует, что это будет работать, но на практике это может быть нормально.