Как напечатать переменную <неполный тип> в GDB
-
04-07-2019 - |
Вопрос
Иногда GDB печатает «неполный тип» для некоторых типов переменных.Что это значит и как мы можем увидеть эту ценность?
Решение
Это означает, что тип этой переменной указан не полностью.Например:
struct hatstand;
struct hatstand *foo;
GDB знает это foo
является указателем на hatstand
структура, но члены этой структуры не определены.Отсюда и «неполный тип».
Чтобы напечатать значение, вы можете привести его к совместимому типу.
Например, если вы знаете, что foo
на самом деле является указателем на lampshade
состав:
print (struct lampshade *)foo
Или вы можете распечатать его как общий указатель или рассматривать его как целое число:
print (void *)foo
print (int)foo
См. также эти страницы из руководства GDB:
Другие советы
Я обнаружил, что если вы разберете функцию, которая использует неполный тип структуры, gdb 'обнаружит' элементы структуры и впоследствии сможет их отобразить. Например, допустим, у вас есть строковая структура:
struct my_string {
char * _string,
int _size
} ;
некоторые функции для создания и получения строки через указатель:
my_string * create_string(const char *) {...}
const char * get_string(my_string *){...}
и тест, который создает строку:
int main(int argc, char *argv[]) {
my_string *str = create_string("Hello World!") ;
printf("String value: %s\n", get_string(str)) ;
...
}
Запустите его в gdb и попробуйте «print * str», и вы получите ответ «неполный тип». Тем не менее, попробуйте 'disassemble get_string', а затем 'print * str', и он будет правильно отображать структуру и значения. Я понятия не имею, почему это работает, но это работает.
У меня была такая же проблема. Если вы загружаете символы из своих библиотек вручную:
set auto-solib-add off
attach thread_id
shared any_lib
shared another_lib
Вам необходимо также загрузить символы из библиотеки, в которой объявлен этот объект, той же командой.
Я не знаю полного значения ошибки, но, как замечает Питер, разборка связанного метода делает то, что делает некоторые из этих определений типов доступными.
Мой пример:
В .h для класса этот класс включал предварительное объявление внутреннего вспомогательного класса, чтобы внешний класс мог содержать указатель на него. Соответствующий .cpp имел полное определение внутреннего вспомогательного класса.
При взломе метода внешнего класса gdb сообщил о неполном типе для разыменования указателя на экземпляр внутреннего класса через экземпляр внешнего класса.
Выполнение команды disasemble в одном из методов внешнего класса позволило gdb понять структуру внутреннего класса, используя тот же указатель, который ранее не удался.
Дисламер
Я разработчик Python, обладающий лишь некоторыми минимальными знаниями C++ и функционированием ОС Linux, поэтому то, что я описываю ниже, — это всего лишь мое решение проблемы, с которой я столкнулся лично.
Если вы пытаетесь работать с типами из сторонних библиотек, убедитесь, что в этих библиотеках нет отладочной информации.
Пример
(gdb) info share Qt
From To Syms Read Shared Object Library
0x00007ffff5336080 0x00007ffff56ba585 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
0x00007ffff4ad3510 0x00007ffff4ef0cbe Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
0x00007ffff47829c0 0x00007ffff47e1ba1 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5DBus.so.5
0x00007ffff40bb5e0 0x00007ffff439dd92 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
0x00007ffff2e581e0 0x00007ffff2e78e4f Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Xml.so.5
0x00007ffff28c8a00 0x00007ffff29d9999 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Network.so.5
0x00007ffff2251750 0x00007ffff2252a46 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5X11Extras.so.5
0x00007ffff1cc9f80 0x00007ffff1cfc861 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5PrintSupport.so.5
0x00007fffee269c10 0x00007fffee297b57 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Svg.so.5
0x00007fffed987560 0x00007fffed98b6a8 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5TextToSpeech.so.5
0x00007fffe980e130 0x00007fffe9900c0c Yes (*) /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5
0x00007fffe69ef650 0x00007fffe69ffe0d Yes (*) /usr/lib/x86_64-linux-gnu/libQt5QuickControls2.so.5
0x00007fffe5c0f890 0x00007fffe5eae1c1 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5
0x00007fffe5522690 0x00007fffe581f636 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Qml.so.5
0x00007fffe51996b0 0x00007fffe5221363 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5QuickTemplates2.so.5
(*): Shared library is missing debugging information.
^ во всех библиотеках Qt в текущем примере отсутствует отладочная информация.Это связано с тем, что отладочная информация для библиотек qt поставляется в отдельных пакетах, которые не устанавливаются.
Всякий раз, когда я делал whatis
все работало нормально:
(gdb) whatis e
type = QEvent *
но когда я попытался получить доступ к его членам
(gdb) p e->type()
Couldn't find method QEvent::type
и пытаюсь получить подробное описание типа
(gdb) ptype e
type = class QEvent {
<incomplete type>
} *
Решение (для Qt в Ubuntu)
- Найдите, к какому пакету в дистрибутиве вашей ОС принадлежит файл.
$ dpkg -S /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
libqt5core5a:amd64: /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
Поиск связанных пакетов
Поиск с помощью клавиатуры
libqt5core5a
вернул 2 посылки, однаlibqt5core5a
сам, а другой естьlibqt5core5a-dbgsym
.В описании последнего сказано:«символы отладки для libqt5core5a»Установите пакеты с символами отладки (я также установил символы отладки для некоторых других важных библиотек Qt)
$ sudo apt install libqt5core5a-dbgsym libqt5widgets5-dbgsym libqt5gui5-dbgsym
- Убедитесь в
gdb
что библиотеки теперь имеют отладочную информацию
(gdb) info share Qt
From To Syms Read Shared Object Library
0x00007ffff5336080 0x00007ffff56ba585 Yes /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
0x00007ffff4ad3510 0x00007ffff4ef0cbe Yes /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
0x00007ffff47829c0 0x00007ffff47e1ba1 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5DBus.so.5
0x00007ffff40bb5e0 0x00007ffff439dd92 Yes /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
0x00007ffff2e571e0 0x00007ffff2e77e4f Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Xml.so.5
0x00007ffff28c7a00 0x00007ffff29d8999 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Network.so.5
0x00007ffff2250750 0x00007ffff2251a46 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5X11Extras.so.5
0x00007ffff1cc8f80 0x00007ffff1cfb861 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5PrintSupport.so.5
0x00007fffee268c10 0x00007fffee296b57 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Svg.so.5
0x00007fffed985560 0x00007fffed9896a8 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5TextToSpeech.so.5
0x00007fffe95fc130 0x00007fffe96eec0c Yes (*) /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5
0x00007fffe701f650 0x00007fffe702fe0d Yes (*) /usr/lib/x86_64-linux-gnu/libQt5QuickControls2.so.5
0x00007fffe623c890 0x00007fffe64db1c1 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5
0x00007fffe5b4f690 0x00007fffe5e4c636 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5Qml.so.5
0x00007fffe57c66b0 0x00007fffe584e363 Yes (*) /usr/lib/x86_64-linux-gnu/libQt5QuickTemplates2.so.5
(*): Shared library is missing debugging information.
- Теперь работа с типами Qt работает как положено.
(gdb) p e->type()
$4 = QEvent::Paint
(gdb) ptype e
type = class QEvent {
public:
...
}