Search code examples
c++stleclipse-cdtcentos6pretty-print

Eclipse/CDT Pretty Print Errors


Let me start by saying that I've scoured other questions on here that are incredibly closely related, but haven't lent themselves to resolving my issue.

Setup:

  • Win7 laptop, SSH/X11 to CentOS 6.4 Final running Eclipse Kepler SR2 w/ CDT 8.3
  • GDB 7.2
  • Managed corporate server that does not have Internet access (so no svn co...)

I am new to using Eclipse/CDT, but familiar with GDB. When I try to debug an application that uses STL, upon the first occurrence of an STL object, I get the below error(s). On programs with many, many STL objects, I get so many errors, that it makes single-stepping impossible. I have here a small sample program for illustration purposes.

Here is my sample program:

#include <iostream>
using namespace std;

int main() {
    string sComplex;
    sComplex = "!!!Hello World!!!";
    cout << sComplex << endl; // prints !!!Hello World!!!
    //cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
    cout << "This is a new string that writes out a numeric..." << endl;
    int i = 1000;
    cout << "Value for integer 'i' is : '" << i << "'." << endl;
    cout << "  In HEX: '";
    cout << std::hex << std::showbase << i;
    cout << "'." <<endl;
    return 0;
}

Here are the errors that print out as soon as it hits the first line (STL string instantiation):

Traceback (most recent call last): File "/usr/lib64/../share/gdb/python/libstdcxx/v6/printers.py", line 558, in to_string return self.val['_M_dataplus']['_M_p'].lazy_string (length = len) RuntimeError: Cannot access memory at address 0xffffffffffffffe8

Traceback (most recent call last): File "/usr/lib64/../share/gdb/python/libstdcxx/v6/printers.py", line 558, in to_string return self.val['_M_dataplus']['_M_p'].lazy_string (length = len) RuntimeError: Cannot access memory at address 0xffffffffffffffe8

Traceback (most recent call last): File "/usr/lib64/../share/gdb/python/libstdcxx/v6/printers.py", line 558, in to_string return self.val['_M_dataplus']['_M_p'].lazy_string (length = len) RuntimeError: Cannot access memory at address 0xffffffffffffffe8

First, notice that there are 3 separate errors for this one object. I have verified that the python pretty print module is installed and I have tried suggestions to limit the length in to_string, but to no avail. If I step past the string instantiation, everything works fine and I can see the simple string value of the variable. Mouse-over looks good too. When I debug this same application using gdb straight on the command-line, I don't see any such errors and variable values print pretty.

(gdb) p sComplex
$1 = "!!!Hello World!!!"
(gdb) p sComplex.c_str()
$2 = 0x602028 "!!!Hello World!!!"

I've tried various suggestions with my .gdbinit file and Eclipse's Window->Preferences->C/C++->Debug->GDB settings, even disabling pretty print, but it still happens. I don't know what else to try next.


Solution

  • I finally decided to revisit this issue and finally resolved it by following solutions similar to this one, and by additional editing of my custom printers.py. Hopefully this helps someone else who's hit this.

    1. Checkout pretty printers (svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python) to $HOME/gdb/gdb_printers/.
      • If you cannot checkout (if your organization blocks external svn like mine does), see if you can copy it from a system location (such as /usr/share/gdb/). You should have a directory structure like this when you're done:

    gdb printer tree

    This structure has to be EXACT or it won't use your printers.py down in /v6/.

    1. Edit printers.py, specifically StdStringPrinter::to_string as follows (adding try/except/else):

      def to_string(self):
          # Make sure &string works, too.
          type = self.val.type
          if type.code == gdb.TYPE_CODE_REF:
              type = type.target ()
      
          # Calculate the length of the string so that to_string returns
          # the string according to length, not according to first null
          # encountered.
          # I wrapped this section in a try/except/else block so that uninitialized
          # strings don't cause massive RuntimeError exception reporting during debugging
          # with or without pretty printers enabled. -jkw
          try:
               ptr = self.val ['_M_dataplus']['_M_p']
               realtype = type.unqualified ().strip_typedefs ()
               reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
               header = ptr.cast(reptype) - 1
               len = header.dereference ()['_M_length']
          except RuntimeError:
               #print 'Caught exception'
               return ''
          else:
               return self.val['_M_dataplus']['_M_p'].lazy_string (length = len)
      
    2. Create/edit $HOME/gdb/.gdbinit file and put the following in it. Note the path must match the path to the 'python' directory in the above image/tree view.

       python
      import sys
      sys.path.insert(0, '/home/(user_id)/gdb/gdb_printers/python')
      from libstdcxx.v6.printers import register_libstdcxx_printers
      register_libstdcxx_printers (None)
      end
      
    3. In Eclipse, under Window -> preferences -> C/C++ -> Debug -> GDB, set the path to gdb and your .gdbinit file. You may also need to set this on any existing debug configurations that you want to use your printers.py.

      GDB debugger: /usr/bin/gdb
      GDB command file: /home/(user_id)/gdb/.gdbinit
      

    From there, debugging functions just as you think it should.