[英]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/libstdcxx
: https : //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 版本。 但是,我必须做这两个模组:
编辑~/.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 已经注册。 显然,他们是在导入阶段注册的。
std::set
和std::map
编辑 printers.py 文件。 由于类型_Rep_type
在两者中都是私有的。 特别是,我将std::map
和std::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 添加了几个命令( pvector
、 plist
、 pmap
等),其功能是打印 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.