如何在DDD(或gdb)中使用unique_ptr调试C++11代码?

13

std::unique_ptr 很好用,但在使用 DDDgdb 调试时,我发现它们不太方便。

我使用的是 gcc 自带的 gdb 漂亮打印机(例如:/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

在DDD中,直接使用Display *pTest的方法也不起作用。它只会导致以下错误:

<error: Could not find operator*.>

如何在DDD中调试使用unique_ptr的C++11代码(而不像我用笨拙的解决方法那样破坏工作流程)?


我不怕使用gdb命令,但DDD集成会更好。例如,通过双击数据结构中的指针跟踪它们通常比键入要快。

我已经尝试删除漂亮打印器,但这也不是最优解。我能想到的最好的解决方案是以下内容:

 print pTest._M_t->_M_head_impl

听起来可能是个愚蠢的问题,但你是否必须从头开始在你的盒子上构建gcc编译器?还是它是一个RPM更新?最近我在尝试调试一些C++ 11代码时遇到了gdb的问题,并发现我没有重新编译gdb。我很确定这里不是这种情况,但我想问问也许值得一试。 - user628985
@Welshboy 我目前正在使用来自Arch Linux的官方gcc 4.8.2(20140206)和gdb 7.7。 - Philipp Claßen
1
你可以尝试这个链接:https://dev59.com/lXRC5IYBdhLWcg3wW_tk,特别是看一下gdbinit文件。看起来有很多自定义的东西可以让gdb做到。祝好运。 - Ben
2个回答

12
这个问题实际上与C++11、unique_ptr或漂亮打印无关。问题在于gcc没有为std::unique_ptr::operator*生成代码,因此gdb无法调用它来取消引用unique_ptr。例如,如果您在代码中添加*pTest;,则gdb会执行取消引用操作。
SO帖子How to `print`/evaluate c++ template functions in gdb中描述了类似的问题。在https://sourceware.org/ml/archer/2012-q1/msg00003.html中描述了一个auto_ptr的几乎相同的问题。如果我正确理解了该线程,其中一种解决方法是修补漂亮的打印机,并在打印unique_ptr时同时打印取消引用的指针。可以在http://sourceware.org/bugzilla/show_bug.cgi?id=12937找到gdb错误报告。 https://sourceware.org/gdb/wiki/STLSupport)中提供了更多漂亮的打印解决方案,可能还有其他解决方法。

编辑:一种更优雅的解决方案是强制编译器显式实例化包括operator*在内的所有成员模板:

template class std::unique_ptr<MyType>;

我应该在哪里定义这个显式实例化? - q0987
从技术角度来看,在包含“memory”头文件并声明“MyType”(或相应的包含文件)之后的一个翻译单元(“cpp文件”)中,可以进行显式实例化 - 参见http://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation - user1225999

3

GDB有一个名为xmethods的功能,允许您在Python中重新实现C++方法。这使得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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接