Вопрос

std::unique_ptr are nice, but I find them less comfortable when debugging in DDD or gdb.

I'm using the gdb pretty printers that are part of gcc (e.g., /usr/share/gcc-4.8.2/python/libstdcxx/v6/printers.py). That is a big win for readability, for example:

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

However, dereferencing the pointer does not work:

$ print *pTest
Could not find operator*.

When I need to access the value, I have to manually copy the pointer and cast it to the correct type, for example:

print *((MyType*) 0x2cef0a0)

If the process is still running, this version works (still ugly but better):

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

The straightforward approach to Display *pTest in DDD does not work either. It only results in the following error:

<error: Could not find operator*.>

Is there a way to debug C++11 code with unique_ptr in DDD (without breaking the workflow like I do with my cumbersome workarounds)?


I'm not afraid to use gdb commands, but DDD integration would be a plus. For example, following pointers in data structures by just double-clicking on them is often faster than typing.

I already tried to drop the pretty printer, but it is also not optimal. The best that I could come up with is the following:

 print pTest._M_t->_M_head_impl
Это было полезно?

Решение

This problem is actually not related to C++11, unique_ptr or pretty printing. The problem is that gcc does not emit code for std::unique_ptr::operator* that could be called by gdb to dereference the unique_ptr. If you for instance add *pTest; to your code then gdb does perform the dereferencing.

A similar problem is described in the SO post How to `print`/evaluate c++ template functions in gdb. Almost the same problem is described for an auto_ptr at https://sourceware.org/ml/archer/2012-q1/msg00003.html. If I understand the thread correctly one workaround would be to patch the pretty printer and also print out the dereferenced pointer when printing the unique_ptr. A gdb bug report can be found at http://sourceware.org/bugzilla/show_bug.cgi?id=12937.

The gdb wiki at https://sourceware.org/gdb/wiki/STLSupport describes more pretty printing solutions, which could have other workarounds.

Edit: A more elegant solution forcing the compiler to emit code for all member templates including operator* is to explicitly instantiate the class:

template class std::unique_ptr<MyType>;

Другие советы

GDB has a feature called xmethods which allows you to reimplement C++ methods in Python. This makes get() and the operator* available in GDB even if the compiler did not explicitly emit code for them.

Make sure that you are loading not only the pretty printers but also the xmethods in your .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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top