My gdb is GNU gdb Red Hat Linux (6.3.0.0-1.162.el4rh) and I can't debug templates. How can I debug templates with this debugger?
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
I was having a hard time trying to get gdb debugging to
work with templates code using gdb 6.8 with code compiled with gcc version 4.4.1
After ripping my hair for a while, I found that it magically
started working perfectly when I add the -fPIC switch to the g++ compile arguments.
Related
In the following code, I create a Builder template, and provide a default implementation to return nothing. I then specialize the template with int, to return a value 37.
When I compile with -O0, the code prints 37, which is the expected result. But when I compile using -O3, the code prints 0.
The platform is Ubuntu 20.04, with GCC 9.3.0
Can anyone helps me understand the behavior?
builder.h
class Builder {
public:
template<typename C>
static C build() {
return 0;
}
};
builder.cc
#include "builder.h"
template<>
int Builder::build<int>() {
return 37;
}
main.cc
#include "builder.h"
#include <iostream>
int main() {
std::cout << Builder::build<int>() << '\n';
}
makefile
CXX_FLAG = -O0 -g
all:
g++ $(CXX_FLAG) builder.cc -c -o builder.o
g++ $(CXX_FLAG) main.cc builder.o -o main
clean:
rm *.o
rm main
You should add a forward declaration for build<int>() to builder.h, like so:
template<>
int Builder::build<int>();
Otherwise, while compiling main.cc, the compiler sees only the generic template, and is allowed to inline an instance of the generic build() function. If you add the forward declaration, the compiler knows you provided a specialization elsewhere, and will not inline it.
With -O3, the compiler tries to inline, with -O0 it will not inline anything, hence the difference.
Your code actually violates the "One Definition Rule": it will create two definitions for Builder::build<int>(), but they are not the same. The standard says the result is undefined, but no diagnostics are required. That is a bit unfortunate in this case, as it would have been helpful if a warning or error message was produced.
I have the following SSCCE:
#include <iostream>
#include <string>
void foo(const std::string &a) {
std::cout << a << std::endl;
}
template <typename... Args>
void bar(Args &&... args) {
[&]() {
[&]() {
foo(args...);
}();
}();
}
int main() {
const std::string x("Hello World!");
bar(x);
}
Under clang++ (3.9.1) this compiles and emits "Hello World". Gcc 6.3 fails with a segmentation fault under -O3.
I can fix the problem by explicitly passing the pointer and the pack by reference, replacing [&]() with [&args...](). However, up to now, I thought that [&] would do the same as listing all arguments one by one.
So what is going wrong here?
P.S:
This is not limited to -O3. -O0 does not segfault but does not return the expected result ("Hello World!"):
[:~/tmp] $ g++-6 -std=c++1z param.cpp && ./a.out
[:~/tmp] $
P.P.S: Further reduced SSCCE. Now I don't even get a diagnostic with -Wall -Wextra anymore.
I strongly suspect a g++ bug.
Here are some notes:
replacing std::string with any elementary type, e.g., int still does not work
clang and VC++ will work just as intended
not passing parameter pack by reference causes an internal compiler error with g++ 7.0.1 with the following output:
internal compiler error: in make_decl_rtl, at varasm.c:1304
...
Please
submit a full bug report, with preprocessed source if appropriate.
Please include the complete backtrace with any bug report. See
http://gcc.gnu.org/bugs.html for instructions.
I used dlopen to load multiple shared libraries which use same type name with different layout in each module. There is no problem when just compiling and running example, but I can't load correct type information for each module in gdb when debugging.
Here is an example I've used to reproduce this situation.
(I've adopted an example from https://stackoverflow.com/a/392421 with modification to add multiple module.)
moduleA.cpp
#include <stdio.h>
enum myEnum {
MY_A=1,
MY_B=2,
MY_C=3,
MY_D=4,
MY_E=5
};
void callback(int v);
extern "C" void foo(void)
{
puts("Hello, I'm a shared library A");
callback(MY_D);
}
moduleB.cpp
#include <stdio.h>
enum myEnum {
MY_A=1,
MY_B=2,
MY_C=100, // different enumeration
MY_D=101,
MY_E=102
};
void callback(int v);
extern "C" void foo(void)
{
puts("Hello, I'm a shared library B");
callback(MY_D);
}
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void callback(int v) {
printf("here, i'm back and MY_D is %d\n", v);
}
int
main(int argc, char **argv)
{
void *handleA, *handleB;
void (*fooA)(void);
void (*fooB)(void);
char *errorA;
char *errorB;
// Use moduleA
handleA = dlopen("./libmoduleA.so", RTLD_LAZY);
*(void **) (&fooA) = dlsym(handleA, "foo");
(*fooA)();
// Use moduleB
handleB = dlopen("./libmoduleB.so", RTLD_LAZY);
*(void **) (&fooB) = dlsym(handleB, "foo");
(*fooB)();
dlclose(handleA);
dlclose(handleB);
exit(EXIT_SUCCESS);
}
When I've compile and run above example, I've got following result as expected.
$ g++ -g -shared -Wall -Werror -fpic -o libmoduleA.so moduleA.cpp
$ g++ -g -shared -Wall -Werror -fpic -o libmoduleB.so moduleB.cpp
$ g++ -g -rdynamic -o a.out main.cpp -ldl
$ ./a.out
Hello, I'm a shared library A
here, i'm back and MY_D is 4
Hello, I'm a shared library B
here, i'm back and MY_D is 101
However when I've tried to use gdb to debug, type information in gdb is not correctly shown for each module.
For example, different myEnum type are defined in module A and B above, e.g. MY_C and later have different value.
If I use gdb to test myEnum type for each module as below, I can't fetch correct enumeration for module B, which is loaded later than module A.
$ gdb a.out
(gdb) b foo
Function "foo" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (foo) pending.
(gdb) r
Breakpoint 1, foo () at moduleA.cpp:15
15 puts("Hello, I'm a shared library A");
(gdb) ptype myEnum
type = enum myEnum {MY_A = 1, MY_B, MY_C, MY_D, MY_E}
(gdb) p/x MY_D
$3 = 0x4
(gdb) n
Hello, I'm a shared library A
16 callback(MY_D);
(gdb) n
here, i'm back and MY_D is 4
17 }
(gdb) c
Continuing.
Breakpoint 1, foo () at moduleB.cpp:15
15 puts("Hello, I'm a shared library B");
(gdb) ptype myEnum
type = enum myEnum {MY_A = 1, MY_B, MY_C, MY_D, MY_E}
(gdb) p/x MY_D
$4 = 0x4
(gdb) n
Hello, I'm a shared library B
16 callback(MY_D);
(gdb)
here, i'm back and MY_D is 101
17 }
(gdb)
I would like to see correct enum myEnum information where MY_D is 101, not 4 for module B.
It seems that correct type information is loaded for module B, if I close moulde A before loading module B. However I want to use both module without closing.
Is there any way to load type information for module B in gdb without closing module A ?
I have the following SSCCE:
#include <iostream>
#include <string>
void foo(const std::string &a) {
std::cout << a << std::endl;
}
template <typename... Args>
void bar(Args &&... args) {
[&]() {
[&]() {
foo(args...);
}();
}();
}
int main() {
const std::string x("Hello World!");
bar(x);
}
Under clang++ (3.9.1) this compiles and emits "Hello World". Gcc 6.3 fails with a segmentation fault under -O3.
I can fix the problem by explicitly passing the pointer and the pack by reference, replacing [&]() with [&args...](). However, up to now, I thought that [&] would do the same as listing all arguments one by one.
So what is going wrong here?
P.S:
This is not limited to -O3. -O0 does not segfault but does not return the expected result ("Hello World!"):
[:~/tmp] $ g++-6 -std=c++1z param.cpp && ./a.out
[:~/tmp] $
P.P.S: Further reduced SSCCE. Now I don't even get a diagnostic with -Wall -Wextra anymore.
I strongly suspect a g++ bug.
Here are some notes:
replacing std::string with any elementary type, e.g., int still does not work
clang and VC++ will work just as intended
not passing parameter pack by reference causes an internal compiler error with g++ 7.0.1 with the following output:
internal compiler error: in make_decl_rtl, at varasm.c:1304
...
Please
submit a full bug report, with preprocessed source if appropriate.
Please include the complete backtrace with any bug report. See
http://gcc.gnu.org/bugs.html for instructions.
i was just making a few changes to my program, when all of a sudden g++ complained with an internal compiler error.
Clang however compiles it without any problems and also does not give any warnings, that would indicate anything weird.
I distilled the problem down to this:
#include <functional>
template<typename T>
class A{
T someVar;
};
template<typename T>
class B {
int x;
std::function<A<double>(A<int>&)> someLambda = [&](A<int>& aInt){
int xVar = x;
A<double> aRet;
return aRet;
};
};
int main(int argc, char** argv){
B<int> a;
return 0;
}
I tried both GCC 4.9.2 and 4.8.4, with both failing (internal compiler error).
Flags I used:
g++ -std=c++11 -O0 -g -Wall main.cpp -o gccBin
clang++ -std=c++11 -O0 -g -Wall main.cpp -o clangBin
main.cpp: In instantiation of 'struct B<int>::<lambda(class A<int>&)>':
main.cpp:10:7: required from here
main.cpp:14:24: internal compiler error: in tsubst_copy, at cp/pt.c:12569
int xVar = x;
^
libbacktrace could not find executable to open
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Clang++(3.5.1) compiles it without a problem, as I mentioned.
I also tried multiple machines, everywhere the same.
Is there some kind of error I overlooked? I searched a bit on the internet and the only similar problems i could find should have been fixed by now (as the bugtracker states).
Could maybe someone try and run this code on their machine or give other advice?
Thank you,
Lazarus
It's a compiler bug. Just go ahead and file a bug report to the GCC dudes!