debug c++ template with 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.

Upvotes: 11

Views: 6414

Answers (2)

Klaus
Klaus

Reputation: 25603

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

Upvotes: 14

Tom Tromey
Tom Tromey

Reputation: 22519

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.

Upvotes: 5

Related Questions