How to pretty-print STL containers in GDB?
C++LinuxDebuggingStlGdbC++ Problem Overview
I've followed the instructions on the GDB wiki to install the python pretty-printers for viewing STL containers. My ~/.gdbinit
now looks like this:
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:
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.
C++ Solutions
Solution 1 - C++
It just works on Ubuntu 17.04
Debian seems to have finally integrated things properly now:
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/releases/gcc-6.3.0/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?
Custom classes
See how to define a custom toString
method and call it at: https://stackoverflow.com/questions/15163261/printing-c-class-objects-with-gdb/58310207#58310207
Inspect specific elements in optimized code
It was hard last time I checked, you get "Cannot evaluate function -- may be in-lined" https://stackoverflow.com/questions/40633787/c-stl-gdb-cannot-evaluate-function-maybe-inlined
On unoptimized code it works: https://stackoverflow.com/questions/427589/inspecting-standard-container-stdmap-contents-with-gdb
Solution 2 - C++
You can try with below GDB macro (append it to your ~/.gdbinit file) to print STL containter types data and even their data members: https://gist.github.com/3978082
Solution 3 - C++
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. However, I had to do these two mods:
-
when editing the
~/.gdbinit
file, the suggested addition ispython 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. Apparently they get registered during the import phase.
- I had to edit the printers.py file for
std::set
andstd::map
. Since the type_Rep_type
is private in both. In particular, I replace the routinechildren
instd::map
andstd::set
with the corresponding one in the version of pretty printer from the gcc-4_6-branch version on the svn repo. Got no error ever since, and stuff prints out nicely now.
Hope this helps.
Solution 4 - C++
Check your gcc version. If it is less than 4.7, you need use another printer.py file. Get the file from http://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch/libstdc++-v3/python/.
Solution 5 - C++
Instead of methods listed in the link you mentioned, you can try the script here,
Do as follows:
-
Download the script to
/your/path
. Name it to some name e.g.your_name.conf
. -
Add a
~/.gdbinit
file to home directory if you don't have one. -
Add a line
source /your/path/your_name.conf
to your~/.gdbinit
. -
Restart gdb. Try
pvector
You can find help information with commands like help pvector
.
e.g.
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. It also adds print pretty
, yielding nice format like this:
Also, if you wanna know how exactly the elements of STL are accessed in gdb, just read the code of the commands. There's no secret in the code. ^_^
e.g.
vectors are accessed by ._M_impl._M_start
p vec._M_impl._M_start + 4 # prints vec[4]
Solution 6 - C++
If you type info type _Rep
after the Python exception, gdb will inform you about the classes loaded that match _Rep. That list could help you to find why python cannot find your std::string class
.
I just faced your problem and in my case was intel c compiler, icc, who broke pretty printing. In particular, unqualified icc name for std::string
results in:
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:
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. 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.
Solution 7 - C++
I think you are using a non-GNU STL library, or possible a very old GCC libstdc++
. The type of a normal STL string on my compiler is: std::basic_string<char, std::char_traits<char>, std::allocator<char> >
. Note that this is not std::basic_string<char>
.
The Python code has this in it:
reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
This look up a nested type ::Rep
of whatever the base string type actually is. The error message inidicates that the string class of whatever strange library you're using doesn't actually have a ::Rep
nested type.
Solution 8 - C++
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).
In theory, LLVM-build program may be debugged by gdb
, and vice versa. But
to avoid problems like posted above, you should use lldb
if you use clang
, and should use gdb
if you use g++
.
Solution 9 - C++
Similar to enter link description here Worked for me in ~/.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