繁体   English   中英

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

[英]How to pretty-print STL containers in GDB?

我已经按照GDB wiki 上的说明安装了 python 漂亮打印机以查看 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 = 

任何人都可以阐明这一点吗? 我正在运行 Ubuntu 12.04,它附带 GDB 7.4。

它只适用于 Ubuntu 17.04

Debian 现在似乎终于正确地整合了一些东西:

主程序

#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/libstdcxxhttps : //github.com/gcc-mirror/gcc/blob/gcc-6_3_0-release /libstdc%2B%2B-v3/python/libstdcxx/v6/printers.py#L244

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

自定义类

查看如何定义自定义toString方法并在以下位置调用它: 使用 GDB 打印 C++ 类对象

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

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

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

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

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

我使用的是 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 版本的漂亮打印机版本中的相应子项。 从那以后没有错误,现在打印出来的东西很好。

希望这可以帮助。

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

您可以在 此处尝试脚本,而不是您提到的链接中列出的方法,

执行以下操作:

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

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

3) 添加一行source /your/path/your_name.conf到你的~/.gdbinit

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)

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

在此处输入图片说明

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

例如,向量由._M_impl._M_start访问

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

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

我刚刚遇到了你的问题,在我的情况下是英特尔 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;

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

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

有了这个:

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

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

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

Python 代码中包含以下内容:

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

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

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

类似于在此处输入链接描述在 ~/.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

我的系统也有这个问题。

对我来说,修复如下

在 ~/.gdbinit

python
import sys
sys.path.insert(0, '<path/to/gcc/dir>/GCCcore/9.3.0/share/gcc-9.3.0/python/')
exec(open("<path/to/gcc/dir>/GCCcore/9.3.0/lib64/libstdc++.so.6.0.28-gdb.py").read())
end

问题是包含漂亮打印机的python文件夹不是 python 搜索path的一部分(就像您通常需要将 python 模块位置添加到$PYTHONPATH一样)。 第一个命令实现了这一点。 下一个问题是现在需要加载漂亮的打印机。 GCC 在我的系统上的GCCcore/9.3.0/lib64/libstdc++.so.6.0.28-gdb.py中提供了执行此操作的脚本。 第二个命令“来源”这个脚本将加载打印机。


聚苯乙烯

在进行此修改之前,我还收到以下错误:

warning: File "<path/to/gcc/dir>/GCCcore/9.3.0/lib64/libstdc++.so.6.0.28-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".

可以通过将以下内容添加到 gdb 初始化文件来修复

add-auto-load-safe-path  <path/to/gcc/dir>/software/GCCcore/9.3.0/

但是,这仍然不允许漂亮的打印机工作(因为路径仍未设置),并且在上面的 python 修复之后,不需要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM