Как отладить код C++11 с unique_ptr в DDD (или GDB)?

std::unique_ptr это хорошо, но я нахожу их менее удобными при отладке в DDD или GDB.

Я использую красивые принтеры GDB, которые являются частью GCC (например, /usr/share/gcc-4.8.2/python/libstdcxx/v6/printers.py). Это большая победа для читабельности, например:

$ print pTest
std::unique_ptr<MyType> containing 0x2cef0a0

Однако разыменование указателя не работает:

$ print *pTest
Could not find operator*.

Когда мне нужно получить доступ к значению, я должен вручную скопировать указатель и привести его к правильному типу, например:

print *((MyType*) 0x2cef0a0)

Если процесс все еще выполняется, эта версия работает (все еще безобразно, но лучше):

print *pTest.get() // will not work if analyzing a core dump

Прямой подход к Display *pTest в DDD тоже не работает. Это приводит только к следующей ошибке:

<error: Could not find operator*.>

Есть ли способ отладки кода C++11 с unique_ptr в DDD (не нарушая рабочий процесс, как я делаю с моими громоздкими обходными путями)?


Я не боюсь использовать команды GDB, но интеграция DDD будет плюсом. Например, следование указателям в структурах данных путем двойного щелчка по ним часто происходит быстрее, чем ввод текста.

Я уже пытался уронить симпатичный принтер, но это тоже не оптимально. Лучшее, что я мог придумать, это следующее:

 print pTest._M_t->_M_head_impl

1 ответ

Решение

Эта проблема на самом деле не связана с C++11, unique_ptr или красивой печатью. Проблема в том, что gcc не генерирует код для std::unique_ptr::operator*, который может быть вызван gdb для разыменования unique_ptr. Если вы, например, добавить *pTest; к вашему коду, тогда GDB выполняет разыменование.

Аналогичная проблема описана в посте SO Как "напечатать" / оценить функции шаблона C++ в gdb. Почти такая же проблема описана для auto_ptr по адресу https://sourceware.org/ml/archer/2012-q1/msg00003.html. Если я правильно понимаю поток, одним из обходных путей будет исправление симпатичного принтера, а также распечатка разыменованного указателя при печати unique_ptr. Отчет об ошибке GDB можно найти по адресу http://sourceware.org/bugzilla/show_bug.cgi?id=12937.

В gdb wiki по адресу https://sourceware.org/gdb/wiki/STLSupport описаны более привлекательные решения для печати, которые могут иметь другие обходные пути.

Редактирование: более элегантное решение, заставляющее компилятор генерировать код для всех шаблонов-членов, включая оператор *, заключается в явном создании экземпляра класса:

template class std::unique_ptr<MyType>;

GDB имеет функцию под названием xmethods, которая позволяет вам повторно реализовать методы C++ в Python. Это делаетget() и operator* доступны в GDB, даже если компилятор явно не выдал для них код.

Убедитесь, что вы загружаете не только красивые принтеры, но и методы xmethods. .gdbinit:

python
import sys
sys.path.insert(0, '/usr/share/gcc-8.2.1/python/')
# This would only enable the printers but not the xmethods:
# from libstdcxx.v6.printers import register_libstdcxx_printers
from libstdcxx.v6 import register_libstdcxx_printers
register_libstdcxx_printers (None)
end
Другие вопросы по тегам