C++ 如何在GDB中漂亮地打印STL容器?

C++ 如何在GDB中漂亮地打印STL容器?,c++,linux,debugging,stl,gdb,C++,Linux,Debugging,Stl,Gdb,我按照说明安装了PythonPretty打印机以查看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类型

我按照说明安装了PythonPretty打印机以查看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 = 
打印myString
Python异常没有名为std::basic_string::_Rep.:的类型
$3 = 

有人能解释一下吗?我运行的是GDB7.4附带的Ubuntu 12.04。

我认为您使用的是非GNU STL库,或者可能是非常旧的GCC
libstdc++
。在我的编译器上,普通STL字符串的类型是:
std::basic_string
。请注意,这不是std::basic_字符串

Python代码中包含以下内容:

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

这将查找一个嵌套类型
::Rep
,不管基字符串类型实际上是什么。错误消息指示您正在使用的任何奇怪库的字符串类实际上没有嵌套类型。

您可以尝试使用下面的GDB宏(将其附加到~/.gdbinit文件)要打印STL容器类型数据甚至其数据成员:

如果在Python异常后键入
info-type\u-Rep
,gdb将通知您加载的与之匹配的类。该列表可以帮助您找到Python找不到
std::string类的原因

我刚刚遇到了你的问题,在我的例子中是英特尔c编译器icc,他打破了漂亮的打印。特别是,
std::string
的非限定icc名称会导致:

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

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

使用从
info type
获得的列表,您可以修复漂亮的打印机,使其正常工作。

检查您的gcc版本。如果小于4.7,则需要使用另一个printer.py文件。从中获取文件。

我处理了这个问题,并在尝试解决问题时点击了此页面。我最终修复了它,我认为分享我的经验是值得的

我使用的是gcc-5.2,所以我从svn repo下载了gcc-5-branch版本的pretty printer。然而,我不得不做这两个MOD:

  • 编辑
    ~/.gdbinit
    文件时,建议添加

    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\u libstdcxx\u printers(None)
    进行注释,因为我不断收到一个错误,告诉我libstdcxx\u打印机已经注册。显然,他们在导入阶段注册

  • 我必须为
    std::set
    std::map
    编辑printers.py文件。因为类型
    \u Rep\u type
    在这两种类型中都是私有的。特别是,我将
    std::map
    std::set
    中的例程
    children
    替换为svn repo上gcc-4_6-branch版本的pretty printer中相应的例程。从那以后就没有出错,现在打印出来的东西很好

  • 希望这能有所帮助。

    它只适用于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));
    }
    
    结果:

    (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}
    
    我们可以看到,pretty打印机安装有:

    (gdb) 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++库包<代码> LBSTDC++6 组成的,位于GCCC源代码< LBSTDC++-V3/Python /LIbSTDCXXX <代码>:

    TODO:GDB如何找到该文件是最后一个疑问,它不在我的Python路径中:
    Python-c“import sys;print('\n.join(sys.path))”
    所以它必须在某个地方硬编码

    自定义类

    请参见如何定义自定义
    toString
    方法并在以下位置调用它:

    检查优化代码中的特定元素

    上次我检查的时候很难,你会得到“无法计算函数-可能在直线上”


    对于未优化的代码,它是有效的:

    当程序是LLVM构建(由
    clang
    编译)时,通常会出现上面所述的错误,并且您尝试通过
    gdb
    对其进行调试(应该用于GCC构建程序)。 理论上,LLVM构建程序可以由
    gdb
    调试,反之亦然。但是
    为避免上述问题,如果使用
    clang
    ,则应使用
    lldb
    ;如果使用
    g++
    ,而不是中列出的方法,则应使用
    gdb
    ,您可以尝试该脚本

    按以下步骤进行:

    1) 将脚本下载到
    /your/path
    。将其命名为某个名称,例如
    your_Name.conf

    2) 如果没有主目录,请将
    ~/.gdbinit
    文件添加到主目录

    3) 在
    ~/.gdbinit
    中添加一行
    source/your/path/your_name.conf

    4) 重新启动gdb。尝试
    pvector

    您可以使用
    help pvector
    等命令查找帮助信息

    e、 g

    仅供参考,将几个命令(
    pvector
    plist
    pmap
    等)添加到gdb,其功能是打印STL的元素。它还添加了
    print pretty
    ,产生如下格式:

    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元素,只需阅读命令的代码即可。密码里没有秘密^_^

    e、 g。 向量通过
    \u M\u impl.\u M\u start

    p vec.\u M\u impl.\u M\u start+4打印vec[4]

    类似于 在~/.gdbinit为我工作:

    python
    import sys
    sys.path.insert(0, '/usr/share/gcc-8/python')
    from libstdcxx.v6.printers import register_libstdcxx_printers
    register_libstdcxx_printers (None)
    end
    

    它可以简单地说是C++库改变了它的内部类型和成员变量,而Python模块没有跟上。你能粘贴更多的信息,比如C++源代码、编译器选项等等吗?我刚刚在Ubuntu12.04上测试了这个,它对我很有效。在CEntOS 7上对我很有效。当您启动gdb时,要查看的一个潜在错误是正确的。它可能会打印一个python错误,您可能会错过它。@Evg我还没有进一步研究它。这对我来说很有效,只是我不知道到底是怎么回事。如果你知道细节,请告诉我。这对我来说很有用-
    /usr/share/gcc-7/python/libstdcxx/v6/printers.py
    
    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)
    
    python
    import sys
    sys.path.insert(0, '/usr/share/gcc-8/python')
    from libstdcxx.v6.printers import register_libstdcxx_printers
    register_libstdcxx_printers (None)
    end