Небольшое собрание трюков, которые могут помочь при отладке с использованием GDB. Не претендует на сенсационность, но должно быть полезно для тех, кто только начинает знакомиться с этим замечательным инструментом. Итак, начнём:
Печать содержимого STL контейнеров
Основные способы собраны здесь, но я бы хотел остановиться на наиоболее универсальном способе - gdb-stl-views(нужно добавить в ~/.gdbinit). Он будет работать не только в самых новых версиях, а и в уже устаревших (это является важным фактором для тех, кто не может обновиться). Примеры использования:(gdb) plist some_listСоответственно, для того, чтобы распечатать весь список нужно использовать:
List size = list_size
List type = std::list<element_type, std::allocator<element_type> >
(gdb) plist some_list element_typeА теперь интересные моменты:
elem[0]: $i = ...
...
elem[list_size - 1]: $i = ...
List size = list_size
- Если внутри контейнера хранится умный указатель, то часто для упрощения вывода можно в качестве element_type указать просто указатель (зависит от того, какой умный указатель вы используете. Большая часть из них при reinterpret_cast к указателю даст осмысленный результат). Например, вместо
plist some_list smart_ptr<elem_type>
использоватьplist some_list elem_type*
- Если вы активно используете пространства имён, element_type скорее всего будет доступен только с полным указанием пространств имён, например NS1::NS2::element_type. Интересной особенностью GDB является то, что он не воспринимает NS1::NS2::element_type* как тип. Обойти эту проблему можно заключив имя типа в одинарные кавычки: 'NS1::NS2::element_type'*
- GDB иногда игнорирует using namespace. Поэтому лучше просто полностью указывать имя типа со всеми пространствами имён
- Чем новее у вас версия GDB, тем лучше он работает с пространствами имён. Если есть возможность - поставьте GDB 7.0 и выше
Вывод строк
Если вы активно работаете с разными типами строк, с разным размером символов, то вам пригодится следующий совет. Чтобы вывести строку, которую не желает выводить print, можно использовать:- Команду просмотра памяти x. Например,
(gdb) x/16s some_char_ptr
для вывода 16 первых символов в символьном виде - Можно добавить вот такую функцию в .gdbinit:
define wchar_print
Использовать так:
echo "
set $i = 0
while (1 == 1)
set $c = (char)(($arg0)[$i++])
if ($c == '\0')
loop_break
end
printf "%c", $c
end
echo "
end(gdb) wchar_print some_char_ptr
Однообразно выводит std::string, std::wstring, различные двухбайтные строки. Естественно, конвертация к ASCII строке приводит к потере информации, однако в большинстве случаев это не так важно
Step Out
Самый короткий совет. Step Out делается командой fin или finish. Это почему-то один из самых распространённых вопросов.И the last but not the least: в последнее время я довольно редко пишу в этот блог. Одна из причин тому - для небольших спонтанных записей я веду микроблог. Вторая - банальная нехватка времени. Однако не спешите отписываться: в записной книжке скопилось множество интересных статей, советов и идей. Постараюсь возобновить более-менее равномерное наполнение этого блога.
P.S. Для вывода на экран Qt строк можно использовать вот такое:
define printqstring
printf "(QString)0x%x (length=%i): \"",&$arg0,$arg0.d->size
set $i=0
while $i < $arg0.d->size
set $c=$arg0.d->data[$i++]
if $c < 32 || $c > 127
printf "\\u0x%04x", $c
else
printf "%c", (char)$c
end
end
printf "\"\n"
end