Как красиво печатать контейнеры STL в GDB?

Я следил за инструкциями в вики-странице GDB, чтобы установить python pretty-printers для просмотра контейнеров STL. Мой ~/.gdbinit теперь выглядит следующим образом:

python 
import sys 
sys.path.insert(0, '/opt/gdb_prettyprint/python') 
from libstdcxx.v6.printers import register_libstdcxx_printers 
register_libstdcxx_printers (None) 
end 

Однако, когда я запускаю GDB и пытаюсь напечатать STL-тип, я получаю следующее:

print myString
Python Exception <class 'gdb.error'> No type named std::basic_string<char>::_Rep.: 
$3 = 

Может ли кто-нибудь пролить свет на это? Я запускаю Ubuntu 12.04, который поставляется с GDB 7.4.

Ответ 1

Вы можете попробовать с помощью макроса GDB (добавьте его в файл ~/.gdbinit) для печати данных типов STL и даже их членов данных: https://gist.github.com/3978082

Ответ 2

Он работает только в Ubuntu 17.04

Похоже, что Debian наконец-то все правильно интегрировал:

main.cpp

#include <map>
#include <utility>
#include <vector>

int main() {
    std::vector<int> v;
    v.push_back(0);
    v.push_back(1);
    v.push_back(2);
    std::map<int,int> m;
    m.insert(std::make_pair(0, 0));
    m.insert(std::make_pair(1, -1));
    m.insert(std::make_pair(2, -2));
}

Compile:

g++ -O0 -ggdb3 -o main.out -std=c++98 main.cpp

Результат:

(gdb) p v
$1 = std::vector of length 3, capacity 4 = {0, 1, 2}
(gdb) p m
$2 = std::map with 3 elements = {[0] = 0, [1] = -1, [2] = -2}

Мы видим, что симпатичный принтер установлен с:

info pretty-printer

Который содержит строки:

global pretty-printers:
  objfile /usr/lib/x86_64-linux-gnu/libstdc++.so.6 pretty-printers:
  libstdc++-v6
    std::map
    std::vector

Принтеры предоставляются файлом:

/usr/share/gcc-7/python/libstdcxx/v6/printers.py

который поставляется с основным библиотечным пакетом C++ libstdc++6 и находится под libstdc++-v3/python/libstdcxx в исходном коде GCC: https://github.com/gcc-mirror/gcc/blob/gcc-6_3_0-release/libstdc%2B%2B-v3/python/libstdcxx/v6/printers.py#L244

TODO: как GDB находит, что файл является последней загадкой, его нет в моем пути Python: python -c "import sys; print('\n'.join(sys.path))", поэтому он должен быть где-то жестко закодирован?

Пользовательские классы

Узнайте, как определить пользовательский метод toString и вызвать его по адресу: Печать объектов класса C++ с помощью GDB

Ответ 4

Вместо методов, перечисленных в ссылке, которую вы упомянули, вы можете попробовать скрипт здесь,

Сделайте следующее:

1) Загрузите скрипт в /your/path. Назовите его по какому-либо имени, например, your_name.conf.

2) Добавьте файл ~/.gdbinit в домашний каталог, если у вас его нет.

3) Добавьте source/your/path/your_name.conf в ваш ~/.gdbinit.

4) Перезапустите GDB. Попробуй pvector

Вы можете найти справочную информацию с help pvector таких команд, как help pvector.

например

pvector vec 5      # Prints element[5] in vec
pvector vec 5 10   # Prints elements in range [5, 10] in vec. (5, 6, 7, 8, 9, 10)

FYI, сценарий добавляет несколько команд (pvector, plist, pmap и т.д.) в GDB, функция которого заключается в печати элементов STL. Это также добавляет print pretty, получая хороший формат как это:

enter image description here

Кроме того, если вы хотите знать, как именно элементы STL доступны в gdb, просто прочитайте код команд. Там нет секрета в коде. ^ _ ^

например, к векторам обращаются ._M_impl._M_start

p vec._M_impl._M_start + 4 # prints vec[4]

Ответ 5

Если вы наберете info type _Rep после исключения Python, gdb сообщит вам о загруженных классах, которые соответствуют _Rep. Этот список может помочь вам найти, почему python не может найти ваш std::string class.

Я только что столкнулся с вашей проблемой, и в моем случае был компилятор Intel ccc, который прервал печать. В частности, неквалифицированное имя icc для std::string приводит к:

std::basic_string<char, std::char_traits<char>, std::allocator<char> >::std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep;

но довольно принтер искал неквалифицированное имя gcc:

std::basic_string<char, std::char_traits<char>, std::allocator<char>::_Rep;

Что я сделал для решения своей проблемы, было изменение класса StdStringPrinter в printers.py, добавив неквалифицированное имя строки к typename, чтобы посмотреть в gdb. Замена строки:

reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()

с этим:

reptype = gdb.lookup_type (str (realtype) + '::' + str (realtype) + '::_Rep').pointer ()

С полученным списком из info type вы можете исправить ваши симпатичные принтеры, чтобы заставить их работать.

Ответ 6

Я столкнулся с этой проблемой и ударил эту страницу, пытаясь понять ее. Я в конце концов исправил это, и я подумал, что стоило бы поделиться своим опытом.

Я использую gcc-5.2, поэтому я загрузил версию прекрасного принтера gcc-5 из svn repo. Тем не менее, мне пришлось сделать эти два мода:

1) при редактировании файла .gitinit предлагаемое дополнение

python
import sys
sys.path.insert(0, '/home/bartgol/.gdb/gdb_printers/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end

Однако мне пришлось прокомментировать строку register_libstdcxx_printers (None), так как я продолжал получать сообщение об ошибке, когда я уже зарегистрировал libstdcxx_printers. По-видимому, они регистрируются во время фазы импорта.

2) Мне пришлось отредактировать файл printers.py для std::set и std::map. Поскольку тип _Rep_type является приватным в обоих. В частности, я заменяю подпрограмму children в std::map и std::set соответствующей в версии довольно принтера из версии ветки gcc-4_6 на svn repo. С тех пор не было никакой ошибки, и теперь материал печатает красиво.

Надеюсь, что это поможет.

Ответ 7

Я думаю, что вы используете библиотеку не GNU STL или возможно очень старый GCC libstdc++. Тип нормальной строки STL в моем компиляторе: std::basic_string<char, std::char_traits<char>, std::allocator<char> >. Обратите внимание, что это не std::basic_string<char>.

В этом коде Python есть это:

reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()

Посмотрите на вложенный тип ::Rep любого типа базовой строки. Сообщение об ошибке указывает, что класс строк какой-либо странной библиотеки, которую вы используете, на самом деле не имеет вложенного типа ::Rep.

Ответ 8

Ошибки, подобные сообщению выше, обычно появляются, когда программа LLVM-build (скомпилирована clang), и вы пытаетесь отладить ее с помощью gdb (которая должна использоваться для программ GCC-build). Теоретически, программа LLVM-build может быть отлажена gdb и наоборот. Но чтобы избежать проблем, описанных выше, вы должны использовать lldb, если вы используете clang, и должны использовать gdb, если вы используете g++.