简体   繁体   English

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

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

I've followed the instructions on the GDB wiki to install the python pretty-printers for viewing STL containers.我已经按照GDB wiki 上的说明安装了 python 漂亮打印机以查看 STL 容器。 My ~/.gdbinit now looks like this:我的~/.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 

However, when I run GDB and attempt to print an STL type, I get the following:但是,当我运行 GDB 并尝试打印 STL 类型时,我得到以下信息:

print myString
Python Exception <class 'gdb.error'> No type named std::basic_string<char>::_Rep.: 
$3 = 

Can anyone shed some light on this?任何人都可以阐明这一点吗? I'm running Ubuntu 12.04, which comes with GDB 7.4.我正在运行 Ubuntu 12.04,它附带 GDB 7.4。

It just works on Ubuntu 17.04它只适用于 Ubuntu 17.04

Debian seems to have finally integrated things properly now: 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));
}

Compile:编译:

g++ -O0 -ggdb3 -o main.out -std=c++98 main.cpp

Outcome:结果:

(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}

We can see that the pretty printer is installed with:我们可以看到漂亮的打印机安装了:

(gdb) info pretty-printer

Which contains the lines:其中包含以下行:

global pretty-printers:
  objfile /usr/lib/x86_64-linux-gnu/libstdc++.so.6 pretty-printers:
  libstdc++-v6
    std::map
    std::vector

The printers are provided by the file:打印机由文件提供:

/usr/share/gcc-7/python/libstdcxx/v6/printers.py

which comes with the main C++ library package libstdc++6 and is located under libstdc++-v3/python/libstdcxx in the GCC source code: https://github.com/gcc-mirror/gcc/blob/gcc-6_3_0-release/libstdc%2B%2B-v3/python/libstdcxx/v6/printers.py#L244它随主 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: how GDB finds that file is the final mistery, it is not in my Python path: python -c "import sys; print('\\n'.join(sys.path))" so it must be hardcoded somewhere? TODO:GDB 如何发现该文件是最终的谜团,它不在我的 Python 路径中: python -c "import sys; print('\\n'.join(sys.path))"所以它必须在某处进行硬编码?

Custom classes自定义类

See how to define a custom toString method and call it at: Printing C++ class objects with GDB查看如何定义自定义toString方法并在以下位置调用它: 使用 GDB 打印 C++ 类对象

Inspect specific elements in optimized code检查优化代码中的特定元素

It was hard last time I checked, you get "Cannot evaluate function -- may be in-lined" C++, STL, GDB: Cannot evaluate function maybe inlined上次我检查很难,你得到“无法评估函数——可能是内联的” C++、STL、GDB:无法评估函数可能是内联的

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

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

I ran on this problem and hit this page while trying to figure it out.我遇到了这个问题并在试图弄清楚时点击了这个页面。 I eventually fixed it, and I thought it would be worth it to share my experience.我最终修复了它,我认为分享我的经验是值得的。

I am using gcc-5.2, so I downloaded the gcc-5-branch version of pretty printer from the svn repo.我使用的是 gcc-5.2,所以我从 svn repo 下载了漂亮打印机的 gcc-5-branch 版本。 However, I had to do these two mods:但是,我必须做这两个模组:

  1. when editing the ~/.gdbinit file, the suggested addition is编辑~/.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

However, I had to comment the line register_libstdcxx_printers (None) , since I kept getting an error telling me the libstdcxx_printers were already registered.但是,我不得不评论register_libstdcxx_printers (None) ,因为我不断收到错误消息,告诉我 libstdcxx_printers 已经注册。 Apparently they get registered during the import phase.显然,他们是在导入阶段注册的。

  1. I had to edit the printers.py file for std::set and std::map .我必须为std::setstd::map编辑 printers.py 文件。 Since the type _Rep_type is private in both.由于类型_Rep_type在两者中都是私有的。 In particular, I replace the routine children in std::map and std::set with the corresponding one in the version of pretty printer from the gcc-4_6-branch version on the svn repo.特别是,我将std::mapstd::set的例程children替换为 svn repo 上 gcc-4_6-branch 版本的漂亮打印机版本中的相应子项。 Got no error ever since, and stuff prints out nicely now.从那以后没有错误,现在打印出来的东西很好。

Hope this helps.希望这可以帮助。

Check your gcc version.检查您的 gcc 版本。 If it is less than 4.7, you need use another printer.py file.如果小于 4.7,则需要使用另一个 printer.py 文件。 Get the file from http://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch/libstdc++-v3/python/ .http://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch/libstdc++-v3/python/获取文件。

Instead of methods listed in the link you mentioned , you can try the script here ,您可以在 此处尝试脚本,而不是您提到的链接中列出的方法,

Do as follows:执行以下操作:

1) Download the script to /your/path . 1) 将脚本下载到/your/path Name it to some name eg your_name.conf .将其命名为某个名称,例如your_name.conf

2) Add a ~/.gdbinit file to home directory if you don't have one. 2) 如果没有~/.gdbinit文件, ~/.gdbinit添加到主目录。

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

4) Restart gdb. 4) 重启 gdb。 Try pvector试试pvector

You can find help information with commands like help pvector .您可以使用help pvector等命令查找帮助信息。

eg例如

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)

FYI, the script adds several commands ( pvector , plist , pmap etc.) to gdb whose function is to print the elements of STL.仅供参考, 该脚本向 gdb 添加了几个命令( pvectorplistpmap等),其功能是打印 STL 的元素。 It also adds print pretty , yielding nice format like this:它还添加了print pretty ,产生了这样的好格式:

在此处输入图片说明

Also, if you wanna know how exactly the elements of STL are accessed in gdb, just read the code of the commands.另外,如果您想知道在 gdb 中究竟如何访问 STL 的元素,只需阅读命令的代码即可。 There's no secret in the code.代码中没有秘密。 ^_^ ^_^

eg vectors are accessed by ._M_impl._M_start例如,向量由._M_impl._M_start访问

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

If you type info type _Rep after the Python exception, gdb will inform you about the classes loaded that match _Rep.如果在 Python 异常之后键入info type _Rep ,gdb 将通知您加载的与 _Rep 匹配的类。 That list could help you to find why python cannot find your std::string class .该列表可以帮助您找到为什么 python 找不到您的std::string class

I just faced your problem and in my case was intel c compiler, icc, who broke pretty printing.我刚刚遇到了你的问题,在我的情况下是英特尔 c 编译器 icc,他破坏了漂亮的打印。 In particular, unqualified icc name for std::string results in:特别是, 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;

but pretty printer was looking for unqualified gcc name:但是漂亮的打印机正在寻找不合格的 gcc 名称:

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

What I did to solve my problem was modifying class StdStringPrinter in printers.py, adding the unqualified name of the string to the typename to look in gdb.我为解决我的问题所做的是修改StdStringPrinter中的类StdStringPrinter ,将字符串的非限定名称添加到typename以在gdb中查找。 Replacing the line:更换线路:

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

with this:有了这个:

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

With the obtained list from info type you could fix your pretty printers to make them work.使用从info type获得的列表,您可以修复漂亮的打印机以使其工作。

I think you are using a non-GNU STL library, or possible a very old GCC libstdc++ .我认为您使用的是非 GNU STL 库,或者可能是非常旧的 GCC libstdc++ The type of a normal STL string on my compiler is: std::basic_string<char, std::char_traits<char>, std::allocator<char> > .我的编译器上普通 STL 字符串的类型是: std::basic_string<char, std::char_traits<char>, std::allocator<char> > Note that this is not std::basic_string<char> .请注意,这不是std::basic_string<char>

The Python code has this in it: Python 代码中包含以下内容:

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

This look up a nested type ::Rep of whatever the base string type actually is.这将查找任何基本字符串类型的嵌套类型::Rep The error message inidicates that the string class of whatever strange library you're using doesn't actually have a ::Rep nested type.该错误消息表明您使用的任何奇怪库的字符串类实际上都没有::Rep嵌套类型。

Errors like you post above usually appears when program is LLVM-build (compiled by clang ), and you try to debug it by gdb (which should be used for GCC-build programs).当程序是 LLVM-build(由clang编译)时,通常会出现像您上面发布的错误,并且您尝试通过gdb (应该用于 GCC-build 程序)调试它。 In theory, LLVM-build program may be debugged by gdb , and vice versa.理论上,LLVM-build 程序可以通过gdb进行调试,反之亦然。 But to avoid problems like posted above, you should use lldb if you use clang , and should use gdb if you use g++ .但是为了避免上面发布的问题,如果使用clang应该使用lldb ,如果使用g++应该使用gdb

Similar to enter link description here Worked for me in ~/.gdbinit:类似于在此处输入链接描述在 ~/.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

I had this problem on my system as well.我的系统也有这个问题。

For me the fix was the following对我来说,修复如下

In ~/.gdbinit在 ~/.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

The issues is that the python folder that contains the pretty printers was not part of python's search path (just like you would normally need to add your python modules location to $PYTHONPATH ).问题是包含漂亮打印机的python文件夹不是 python 搜索path的一部分(就像您通常需要将 python 模块位置添加到$PYTHONPATH一样)。 The first command accomplishes that.第一个命令实现了这一点。 The next issue is that now the pretty printers need to be loaded.下一个问题是现在需要加载漂亮的打印机。 GCC provides a script for doing so in GCCcore/9.3.0/lib64/libstdc++.so.6.0.28-gdb.py on my system. GCC 在我的系统上的GCCcore/9.3.0/lib64/libstdc++.so.6.0.28-gdb.py中提供了执行此操作的脚本。 The second command 'sources' this script which will load the printers.第二个命令“来源”这个脚本将加载打印机。


PS聚苯乙烯

Before making this modification I also got the following error:在进行此修改之前,我还收到以下错误:

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".

Which can be fixed by adding the following to the gdb init file可以通过将以下内容添加到 gdb 初始化文件来修复

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

However, this still does not allow the pretty printers to work (because of the path still not being set), and after the python fix above, is not needed.但是,这仍然不允许漂亮的打印机工作(因为路径仍未设置),并且在上面的 python 修复之后,不需要。

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

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