debugging templates with GDB
if your problem is just about placing breakpoint in your code. Here is a little snippet
ex: main.cpp
#include <iostream>
template <typename T>
void coin(T v)
{
std::cout << v << std::endl;
}
template<typename T>
class Foo
{
public:
T bar(T c)
{
return c * 2;
}
};
int main(int argc, char** argv)
{
Foo<int> f;
coin(f.bar(21));
}
compile with
g++ -O0 -g main.cpp
gdb ./a.out
(gdb) b Foo<int>::bar(int)
Breakpoint 2 at 0x804871d: file main.cpp, line 16.
(gdb) b void coin<int>(int)
Breakpoint 1 at 0x804872a: file main.cpp, line 6.
(gdb) r
... debugging start
otherwise you could just use
(gdb) b main.cpp:16
debug c++ template with gdb
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.
debugging C++ code with templates and STL with gdb
I am assuming that you mean visualizing STL code better (and not the debug mode which give safe iterators and additional runtime checks). I am not sure if you have looked at these posts:
- GNU GCC Documentation: Debugging Support
Using gdb
Starting with version 7.0, GDB includes support for writing pretty-printers in Python. Pretty printers for STL classes are distributed with GCC from version 4.5.0. The most recent version of these printers are always found in libstdc++ svn repository. To enable these printers, check-out the latest printers to a local directory:
- Pretty printing STL lists
Also, try using KDevelop/DDD if possible -- they do help.
Will my gdb work when using templates?
Normal Class
class foo
{
private:
int x;
public:
foo(int n = 0):x(n) {cout<<"foo::foo(int)"<<endl;}
~foo() {cout<<"foo::~foo()"<<endl;}
};
To put the breakpoint, we follow as below
$gdb: b foo::foo(int)
b foo::~foo()
=========================================================
Template class Example
template<typename T>
class bar
{
private:
T x;
public:
bar(T n = 0):x(n) {cout<<"bar::bar(int)"<<endl;}
~bar() {cout<<"bar::~bar()"<<endl;}
};
To put the breakpoint, we follow as below
$gdb: b bar<int>::bar(int)
b foo<int>::~bar()
The only thing we need to understand is(which I guess confuted you), that when we debug template class, we can not use the break point like bar<T>::bar()
. When program runs, program would instantiate the template class with a particular type as bar<int>::bar()
.
Apart from that, there is no difference while debugging the non-template vs template based class. Only thing we need to consider is, template bases class would be bit verbose and it takes some time to understand especially.
how to print value returned by template member function in gdb/lldb debugging
The current debug information for template functions, and templated entities in general is awkward because it only describes instantiations, and not templates as abstract entities, so templated functions just show up in the debug info just as functions with angle brackets somewhere in the names. That makes it tricky to go from the debug info to a compiler representation that lldb can feed into its copy of clang so that clang can parse them correctly in expressions. As you have found, that doesn't work at present.
If you really need to do this however, you can work around the problem with a little creative casting, for instance:
Find the function address, e.g.
(lldb) image lookup -n Mat::at<float>
1 match found in /tmp/a.out:
Address: a.out[0x0000000100003f30] (a.out.__TEXT.__text + 64)
Summary: a.out`float const& Mat::at<float>(int, int) at template_fun.cpp:4
Cast the call to that address by hand:
(lldb) expr ((float &(*) (Mat *, int, int))0x0000000100003f30)(&my_mat, 10, 20)
Called with 10 20
(float) $0 = 30
This isn't your real function, just a toy I made so don't pay attention to the actual result.
Note, if you end up doing this often and don't 100% love C function casting syntax, you can make a typedef for it, either in the code or in lldb like:
(lldb) expr typedef float &(*$Mat_at_type) (Mat *, int, int)
That simplifies the call:
(lldb) expr (($Mat_at_type)0x0000000100003f30)(&my_mat, 10, 20)
Called with 10 20
(float) $1 = 30
And then if you end up doing this a whole lot, you could even do:
(lldb) command alias call_at expr -- (($Mat_at_type)0x0000000100003f30)
(lldb) call_at (&my_mat, 10, 20)
Inspect template parameter pack in gdb
Related: Showing values of parameters packs in gdb
There are two problems here; the first is that g++ emits parameter pack debugging information in the DWARF format using the tags DW_TAG_GNU_template_parameter_pack
and DW_TAG_GNU_formal_parameter_pack
, which gdb does not yet support (PR linked).
Even when this is fixed, we run into another problem, which is that the debugging information g++ emits is broken; it's missing the parameter name (DW_AT_name
) (PR linked).
TBH gdb support for C++11 is pretty abysmal (unsurprising as it was effectively abandoned for so long); another near-showstopper bug for C++11 is that it didn't support rvalue references (DW_TAG_rvalue_reference_type
) until version 8, printing error messages like <unknown type in /tmp/a.out, CU 0x0, DIE 0x7f>
.
The workaround (other than using clang, or an ancient version of g++ that doesn't use the DW_TAG_GNU_template_parameter_pack
tags, e.g. 4.4.7) is to use the stabs debugging format with GCC extensions:
g++ -std=c++11 -gstabs+ -O0 foo.cxx
</>
(gdb) s
void printAll<int, char const (&) [3], int>(int, int&&, char const (&) [3], int&&) (i=999, args#0=@0x7fffffffe45c: 1, args#1=..., args#2=@0x7fffffffe458: 4)
at p.cpp:7
7 swallow{0,
(gdb) p 'args#0'
$1 = (int &) @0x7fffffffe45c: 1
Related Topics
Non-Type Variadic Function Templates in C++11
Extern "C" Linkage Inside C++ Namespace
How to Get Vendor Id and Product Id of a Plugged Usb Device on Windows
How to Read Input When Debugging in C++ in Visual Studio Code
Qtextedit with Different Text Colors (Qt/C++)
How to Resize an Image to a Specific Size in Opencv
Using Std::Variant with Recursion, Without Using Boost::Recursive_Wrapper
C++ Regular Expressions with Boost Regex
Std::Istream_Iterator<> with Copy_N() and Friends
How to Get a List Video Capture Devices Names (Web Cameras) Using Qt (Crossplatform)? (C++)
Cost of Using Std::Map with Std::String Keys VS Int Keys
Using Raii to Manage Resources from a C-Style API
Modifying Reference Member from Const Member Function in C++
What Is The Correct Behavior of Pthread_Mutex_Destroy When Destroying a Locked Mutex
Emplace an Aggregate in Std::Vector