64

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.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Nick Hutchinson
  • 5,044
  • 5
  • 33
  • 34
  • 7
    It could simply be that the C++ library have changed its internal types and member variables, and the Python module haven't been keeping up. – Some programmer dude Jul 23 '12 at 07:21
  • Could you please paste more information, such as the C++ source, compiler options etc? I just tested this on Ubuntu 12.04 and it works for me. – user1202136 Aug 14 '12 at 15:53
  • Worked for me on CEntOS 7. One potential error to look is right when you start gdb. It might print a python error that you could have missed. – user666412 Nov 21 '18 at 20:12
  • (*advertisement*) There are some things I don't like about the default pretty-printers `libstdcxx`, so [I made some modifications](https://github.com/user202729/gdb-custom-printers). – user202729 Dec 05 '21 at 06:02

10 Answers10

14

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: Printing C++ class objects with GDB

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

On unoptimized code it works: Inspecting standard container (std::map) contents with gdb

user202729
  • 3,358
  • 3
  • 25
  • 36
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • @Evg I haven't looked further into it. It works for me, just I don't know how exactly. Let me know if you find out the detail. – Ciro Santilli OurBigBook.com Dec 15 '18 at 18:53
  • 1
    Regarding the TODO (from https://gcc.gnu.org/legacy-ml/libstdc++/2009-02/msg00056.html): Printers can be auto-loaded by gdb when it reads an objfile. gdb looks for a file that is the objfile's real name with "-gdb.py" added; e.g., libstdc++.so.6.0.11-gdb.py. – Rosen Matev Apr 19 '22 at 19:25
11

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

Fei
  • 1,450
  • 1
  • 17
  • 30
6

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:

  1. when editing the ~/.gdbinit file, the suggested addition is

    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. Apparently they get registered during the import phase.

  1. I had to edit the printers.py file for std::set and std::map. Since the type _Rep_type is private in both. 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. Got no error ever since, and stuff prints out nicely now.

Hope this helps.

Adrian W
  • 4,563
  • 11
  • 38
  • 52
bartgol
  • 1,703
  • 2
  • 20
  • 30
  • 1
    This worked for me with custom-compiled GDB on Ubuntu 18.04 and gcc-9 from `ubuntu-toolchain-r/test` repo. I just had to alter the path to `/usr/share/gcc-9/python/`. – Ruslan Jan 13 '20 at 08:44
5

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

Bingfeng
  • 147
  • 1
  • 9
4

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. Name it to some name e.g. your_name.conf.

2) Add a ~/.gdbinit file to home directory if you don't have one.

3) Add a line source /your/path/your_name.conf to your ~/.gdbinit.

4) 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:

enter image description here

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]

Scott Yang
  • 339
  • 3
  • 6
3

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
Yotam
  • 808
  • 8
  • 10
2

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.

2

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

Ans
  • 527
  • 5
  • 9
1

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.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
0

I had this problem on my system as well.

For me the fix was the following

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

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.

Cole
  • 600
  • 6
  • 12