Question

How do you call operator<<(std::ostream &os, const ClassX &x) from inside gdb ?

In other words, how do you print an object in gdb ?

call std::cout<<x or call operator<<(std::cout, x) don't seems to work for me!

Any ideas?

Was it helpful?

Solution

The only way I found was this:

call 'operator<<(std::ostream&, myclass&)'(mycout, c)

Since std::cout wasn't visible to gdb for some reason, I had to resort to creating my own like this:

std::ostream mycout(std::cout.rdbuf());

You haven't stated any reasons for wanting to do this but won't print yourvariable be easier?

If this is an absolute must you could have a Print method in your class and call that from operator<< and then call the Print method on your object from gdb.

Do take note that stdout is probably buffered in gdb so you won't be seeing any output unless you redirect it somehow.

See this discussion from gdb's mailing archive regarding this issue.

OTHER TIPS

You can also define a function like:

define printType
call operator<<(std::ostream&, const $arg0 &)(std::cerr, $arg1)
end

And use it like:

printType ClassX objectOfClassX

For me call operator<< ran without error, but didn't print. Turns out I needed a call to flush. Here's a useful function you can put in .gdbinit:

define str
    call (void)operator<<(std::cout, $arg0)
    call (void)std::cout.flush()
    printf "\n"
end

I have the following in my .gdbinit. The previous answers here did not work for me when the operator<< is a template or required a lot of typing to get the types right. This approach searches the symbol table to find the correct operator<<. This only works if the operators have been instantiated explicitly.

python
import gdb
import re
class LexicalCast(gdb.Command):
    def __init__(self):
        super(LexicalCast, self).__init__("lexical_cast", gdb.COMMAND_DATA)

    def matches(self, symbol, type, exact=True):
        params = symbol.find('('), symbol.find(')')
        if -1 in params: return False
        params = symbol[params[0]+1 : params[1]]
        if re.match("^%s, %s( const)?&?$"%(re.escape("std::ostream&"), re.escape(type)), params): return True
        if not exact and re.match("^%s, .*::%s( const)?&?$"%(re.escape("std::ostream&"), re.escape(type)), params): return True
        return False

    def invoke(self, arg, from_tty):
        value = gdb.parse_and_eval(arg)
        type = str(value.type.strip_typedefs().unqualified())
        # isn't unqualified() supposed to do that already?
        if type.startswith("const "): type = type[6:]
        if type.startswith("struct "): type = type[7:]
        if type.endswith(" &"): type = type[:-2]
        # there's probably a better way to browse the list of symbols ...
        shift_operators = gdb.execute("info functions operator<<", False, True).split('\n')  
        matching_operators = [ op for op in shift_operators if self.matches(op, type)]
        if not matching_operators:
            gdb.write("No operator<<(std::ostream&, const %s&) found in the symbols. Trying to find a match with additional namespace qualifiers.\n"%(type,))
            matching_operators = [ op for op in shift_operators if self.matches(op, type, False)]

        if not matching_operators:
            gdb.write("No operator<<(std::ostream&, const .*::%s&) found in the symbols. Did you forget to explicitly instantiate your operator?\n"%(type,))     
        else:
            if len(matching_operators) > 1:
                gdb.write("Found multiple operator<< matching this expression; trying to call each one of them...\n")                          
            for op in matching_operators:
                try:                     
                    op = op.split('  ', 1)[1][:-4] if op.endswith("@plt") else op.split(':', 1)[1].split('&', 1)[1].strip()[:-1]
                    gdb.execute("call (void)'%s'((std::cout), (%s))"%(op, arg))      
                    gdb.execute("call (void)std::cout.put('\\n')")
                    gdb.execute("call (void)std::cout.flush()")
                    break
                except Exception as e:
                    gdb.write("Could not invoke %s: %s\n"%(op, e))

LexicalCast()
end   

In GDB I use it like this:

(gdb) lex sector[0]
4: 1 ~ ([-3.00170 +/- 3.86e-6], [-1.73303 +/- 7.55e-8])
(gdb) lex 123
No operator<<(std::ostream&, const int&) found in the symbols. Did you explicitly instantiate that operator?

This is mostly a hack of course that likely breaks if you have changed how GDB prints info functions, but it works well for my purposes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top