Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

debug c++ template with gdb

Tags:

c++

gdb

When I debug inside a function with template,

  1. How do I know which template type the current function is using?

    I tried p T. It says gdb cant print a type.

  2. How do I break on a particular template type?

    Lets say function foo<T>(...) have 2 possible forms, foo<int>(...) and foo<long>(...) . How do I set a breakpoint so that gdb only pauses on the first one which uses int, but not the second one which uses long?

Edit: It would be nice if the breakpoint can be set by line number. There are many good reasons for this, eg. the initial part of function may take long to run, the place I wish to debug may be inside an if statement etc.

like image 792
Fermat's Little Student Avatar asked Nov 11 '15 22:11

Fermat's Little Student


2 Answers

To set a breakpoint to all instances use:

gdb> rbreak Foo<.*>

To only set a breakpoint on a known instance

gdb> break Foo<int>

You can also use rbreak Foo<int> but it makes no sense to use a call witch evaluates regular expressions but you give none :-)

Example Code:

#include <iostream>
#include <string>

template < typename T>
T Foo(T t) { return t; }

int main()
{
    std::cout << Foo<int>(1) << std::endl;
    std::cout << Foo<std::string>("Hallo") << std::endl;
}

Simply compile with debug info:

g++ main.cpp -g -o go

Run gdb:

gdb go

And test:

gdb> rbreak Foo<int>
gdb> run
gdb> backtrace
gdb> cont

As you can see: Only one instance of the template is affected.

In the backtrace you can see which template instance is called:

#0  Foo<int> (t=1) at main.cpp:5
#1  0x0000000000400b69 in main () at main.cpp:9

As you can see it is Foo<int> here.

To answer a comment: "Is there a way to place a breakpoint in the specific known instance at a certain line?"

Yes!

gdb> break main:692
gdb> info break

this will return something like

Num     Type           Disp Enb Address            What
5       breakpoint     keep y   <MULTIPLE>         
5.1                         y   0x00000000004026db in Foo<int>(int) at main.cpp:692
5.2                         y   0x00000000004027a6 in Foo<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) at main.cpp:692
(gdb)

Now you can disable specific instances with:

gdb> disable 5.2

You can not delete a specific "sub breakpoint". But disable is quite what you need. You can also give a range of instances if you like with e.g.:

gdb> disable 5.1-2
like image 177
Klaus Avatar answered Sep 19 '22 14:09

Klaus


You can use ptype rather than p to print a type. With a recent enough (couple of years old) g++ and gdb, this will work.

Consider this source:

#include <iostream>

template<typename T>
struct S
{
  S(T t)
  {
    std::cout << t;
  }
};

int main()
{
  S<const char*> s2("hello");
  S<int> s1(23);
  return 0;
}

Here I can step into the constructor for s2 and see T:

(gdb) ptype T
type = const char *

Take a look the current frame:

(gdb) frame
#0  S<char const*>::S (this=0x7fffffffe35f, t=0x400940 "hello") at q.cc:8
8       std::cout << t;

I can set a breakpoint using the function name given there:

(gdb) b S<const char *>::S
Breakpoint 2 at 0x40087a: file q.cc, line 8.
like image 38
Tom Tromey Avatar answered Sep 19 '22 14:09

Tom Tromey