【问题标题】:How to pretty-print STL containers in GDB?如何在 GDB 中漂亮地打印 STL 容器?
【发布时间】:2012-07-21 07:20:53
【问题描述】:

我已经按照on the GDB wiki 的说明安装了用于查看 STL 容器的 python 漂亮打印机。我的~/.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 = 

任何人都可以对此有所了解吗?我正在运行 GDB 7.4 附带的 Ubuntu 12.04。

【问题讨论】:

  • 可能只是C++库改变了它的内部类型和成员变量,而Python模块没有跟上。
  • 能否请您粘贴更多信息,例如 C++ 源代码、编译器选项等?我刚刚在 Ubuntu 12.04 上测试了它,它对我有用。
  • 在 CEntOS 7 上为我工作。当你启动 gdb 时,一个潜在的错误是正确的。它可能会打印一个您可能错过的 python 错误。
  • (advertisement) 我不喜欢默认的漂亮打印机libstdcxx,所以I made some modifications

标签: c++ linux debugging stl gdb


【解决方案1】:

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

编译:

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}

我们可以看到漂亮的打印机安装有:

(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++ 库包 libstdc++6 一起提供,位于 GCC 源代码中的 libstdc++-v3/python/libstdcxx 下: https://github.com/gcc-mirror/gcc/blob/releases/gcc-6.3.0/libstdc%2B%2B-v3/python/libstdcxx/v6/printers.py#L244

TODO:GDB 是如何发现该文件是最后的谜团,它不在我的 Python 路径中:python -c "import sys; print('\n'.join(sys.path))" 所以它必须在某个地方进行硬编码?

自定义类

了解如何定义自定义 toString 方法并在以下位置调用它:Printing C++ class objects with GDB

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

上次我检查时很难,你得到“无法评估函数——可能是内联的”C++, STL, GDB: Cannot evaluate function maybe inlined

在未优化的代码上有效:Inspecting standard container (std::map) contents with gdb

【讨论】:

  • @Evg 我没有进一步研究它。它对我有用,只是我不知道具体如何。如果您了解详细信息,请告诉我。
【解决方案2】:

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

我使用的是 gcc-5.2,所以我从 svn repo 下载了漂亮打印机的 gcc-5-branch 版本。然而,我不得不做这两个模组:

  1. 编辑~/.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_libstdcxx_printers (None) 行,因为我不断收到错误消息,告诉我 libstdcxx_printers 已经注册。显然,它们在导入阶段进行了注册。

  1. 我必须为std::setstd::map 编辑printers.py 文件。由于_Rep_type 类型在两者中都是私有的。特别是,我将std::mapstd::set 中的例程children 替换为来自svn repo 上的gcc-4_6-branch 版本的漂亮打印机版本中的相应例程。从那以后再也没有出现错误,现在打印出来的东西很好。

希望这会有所帮助。

【讨论】:

  • 这适用于我在 Ubuntu 18.04 上自定义编译的 GDB 和来自ubuntu-toolchain-r/test repo 的 gcc-9。我只需要将路径更改为/usr/share/gcc-9/python/
【解决方案3】:

类似于enter link description here 在 ~/.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

【讨论】:

    【解决方案4】:

    除了the link you mentioned中列出的方法,你可以试试脚本here

    如下操作:

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

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

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

    4) 重启 gdb。试试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)
    

    仅供参考,the script 向 gdb 添加了几个命令(pvectorplistpmap 等),其功能是打印 STL 的元素。它还添加了print pretty,产生了这样的漂亮格式:

    另外,如果您想知道在 gdb 中究竟是如何访问 STL 的元素,只需阅读命令的代码即可。代码中没有秘密。 ^_^

    例如 向量被._M_impl._M_start访问

    p vec._M_impl._M_start + 4 # prints vec[4]

    【讨论】:

      【解决方案5】:

      当程序是 LLVM 构建(由 clang 编译)时,通常会出现像您上面发布的错误,并且您尝试通过 gdb 调试它(应该用于 GCC 构建程序)。 理论上,LLVM-build程序可以被gdb调试,反之亦然。但 为了避免上面发布的问题,如果你使用clang,你应该使用lldb,如果你使用g++,你应该使用gdb

      【讨论】:

        【解决方案6】:

        检查您的 gcc 版本。如果小于 4.7,则需要使用另一个 printer.py 文件。从http://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch/libstdc++-v3/python/ 获取文件。

        【讨论】:

          【解决方案7】:

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

          我刚刚遇到了您的问题,在我的情况下是 intel 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;
          

          但漂亮的打印机正在寻找不合格的 gcc 名称:

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

          我为解决我的问题所做的是修改printers.py 中的StdStringPrinter 类,将字符串的非限定名称添加到类型名称中以在gdb 中查找。换行:

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

          用这个:

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

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

          【讨论】:

            【解决方案8】:

            您可以尝试使用以下 GDB 宏(将其附加到您的 ~/.gdbinit 文件中)来打印 STL 容器类型数据甚至它们的数据成员:https://gist.github.com/3978082

            【讨论】:

              【解决方案9】:

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

              Python 代码中有这个:

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

              这会查找嵌套类型::Rep,无论基本字符串类型实际上是什么。错误消息表明您使用的任何奇怪库的字符串类实际上都没有::Rep 嵌套类型。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2018-10-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-08-06
                • 1970-01-01
                • 2011-06-26
                相关资源
                最近更新 更多