Ответ 1
Вы можете попробовать с помощью макроса GDB (добавьте его в файл ~/.gdbinit) для печати данных типов STL и даже их членов данных: https://gist.github.com/3978082
Я следил за инструкциями в вики-странице 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.
Вы можете попробовать с помощью макроса GDB (добавьте его в файл ~/.gdbinit) для печати данных типов STL и даже их членов данных: https://gist.github.com/3978082
Он работает только в 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
Проверьте версию gcc. Если оно меньше 4.7, вам нужно использовать другой файл printer.py. Получите файл из http://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch/libstdc++-v3/python/.
Вместо методов, перечисленных в ссылке, которую вы упомянули, вы можете попробовать скрипт здесь,
Сделайте следующее:
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
, получая хороший формат как это:
Кроме того, если вы хотите знать, как именно элементы STL доступны в gdb, просто прочитайте код команд. Там нет секрета в коде. ^ _ ^
например, к векторам обращаются ._M_impl._M_start
p vec._M_impl._M_start + 4 # prints vec[4]
Если вы наберете 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
вы можете исправить ваши симпатичные принтеры, чтобы заставить их работать.
Я столкнулся с этой проблемой и ударил эту страницу, пытаясь понять ее. Я в конце концов исправил это, и я подумал, что стоило бы поделиться своим опытом.
Я использую 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. С тех пор не было никакой ошибки, и теперь материал печатает красиво.
Надеюсь, что это поможет.
Я думаю, что вы используете библиотеку не 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
.
Ошибки, подобные сообщению выше, обычно появляются, когда программа LLVM-build (скомпилирована clang
), и вы пытаетесь отладить ее с помощью gdb
(которая должна использоваться для программ GCC-build).
Теоретически, программа LLVM-build может быть отлажена gdb
и наоборот. Но
чтобы избежать проблем, описанных выше, вы должны использовать lldb
, если вы используете clang
, и должны использовать gdb
, если вы используете g++
.