I like to cast a void pointer back to unique_ptr<T> with arbitrary type T so that I can dereference it to the contents of it. But with the following simple example:
#include <memory>
class Foo {
public: Foo(){};
};
int main() {
std::unique_ptr<Foo> p1 (new Foo);
void *p2 = (void*)&p1;
return 0;
}
I get the following error and not be able to cast:
$ gdb ./unique-ptr
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
...
(gdb) b 10
Breakpoint 1 at 0x400682: file unique-ptr.cc, line 10.
(gdb) run
Starting program: /home/vagrant/c-test/unique-ptr/unique-ptr
Breakpoint 1, main () at unique-ptr.cc:10
10 return 0;
(gdb) p p1
$1 = std::unique_ptr<Foo> containing 0x603010
(gdb) p p2
$2 = (void *) 0x7fffffffea40
(gdb) p *(std::unique_ptr<Foo>*)p2
A syntax error in expression, near `)p2'.
(gdb)
Actual use case is that I like to print out contents of unique_ptr contained in container class, but this is the issue currently preventing me to go further.
The actual type name created with the template is not std::unique_ptr<Foo>. Obtain the real type name with:
(gdb) ptype p1
type = class std::unique_ptr<Foo, std::default_delete<Foo> > [with _Tp = Foo, _Dp = std::default_delete<Foo>] {
private:
__tuple_type _M_t;
...
From this, I figured out that gdb recognizes std::unique_ptr<Foo, std::default_delete<Foo> >, and I was able to do:
(gdb) p *(std::unique_ptr<Foo, std::default_delete<Foo> > *)p2
$3 = std::unique_ptr<Foo> containing 0x603010
which matches with
(gdb) p p1
$1 = std::unique_ptr<Foo> containing 0x603010
Related
I've got this template function:
template<typename T>
void f(const T* t1, const T* t2) {}
Then in main():
int i = 1;
f(&i, NULL);
It doesn't compile, saying candidate template ignored: could not match 'const T *' against 'int'
If change it into:
int i = 1;
f(&i, nullptr); // same error!
I know I can fix it like this, specifying the type info:
int i = 1;
f<int>(&i, NULL);
Ok, it gets compiled.
But isn't it that, c++ compiler could do type deduction for us : so that we can call template functions without specifying all the type information?
Seems NULL/nullptr here is an unusual case for template.
My question: is there a way to go without f<int> in each place, just f, when there's NULL/nullptr?
Thanks.
The compiler uses both parameter to deduce T, and because neither nullptr nor NULL are of type int* there is a conflict between the types deduced from &i and from nullptr / NULL.
Note that nullptr is of type nullptr_t. It can be converted to any other pointer type, but nullptr_t is a distinct type.
Since C++20 you can use std::type_identity to establish a non-deduced context:
#include <type_traits>
template<typename T>
void f(const T* t1, const std::type_identity_t<T>* t2) {}
int main() {
const int* x;
f(x,nullptr); // calls f<int>
}
The second parameter will then not be used to deduce T. Whether this is really what you want depends on details of f. Before C++20, the trait is rather simple to write yourself (see possible implementation).
do we need to explicitly specify type info for template function, when using NULL/nullptr
To know the answer, we need to know the type of the variable/function/macro being used for.
Hence when facing any error or warning during compilation,
f(&i, nullptr); // same error!
learn gdb/dbx/gdb.exe to know the type of the variable or function using
ptype variable_name
ptype function_name
Once known, we can add related type casting to remove that error and warning.
When "ptype variable_name" not working,
Search related macro/function using related header/c/C++ file.
I thought of sharing my comment.
Like the way of your polymorphism using multiple comments :) at stackoverflow.
#include <iostream>
using namespace std;
template<typename T>
// FIRST PARAMETER AND SECOND PARAMETER NEEDS TO BE A POINTER USING SAME TYPE const T*
void f(const T* t1, const T* t2)
{
return;
}
int main()
{
int i = 1;
f( &i, (int*)NULL );
f<int>( &i, NULL );
// f( &i, NULL ); // PASSING int* and char*
float f1 = 20.22;
f<float>( &f1, NULL);
return 0;
}
/* g++.exe -Wall -g 73526963.cpp -o ./a.out
* OR
* g++ -Wall -g 73526963.cpp -o ./a.out
* LEARN debugging using gdb/dbx/gdb.exe based on your operating system.
* Know the prototype of the function and polymorphism using ptype/where for parameters inside gdb.
$ gdb ./a.out
Reading symbols from ./a.out...
(gdb) break main
Breakpoint 1 at 0x10040108d: file 73526963.cpp, line 11.
(gdb) run
Starting program: ./a.out
[New Thread 936.0x474]
[New Thread 936.0x634]
[New Thread 936.0x480]
[New Thread 936.0x2578]
Thread 1 "a.out" hit Breakpoint 1, main () at 73526963.cpp:11
warning: Source file is more recent than executable.
11 int i = 1;
(gdb) next
12 f( &i, (int*)NULL );
(gdb) step
f<int> (t1=0xffffcbec, t2=0x0) at 73526963.cpp:7
7 return;
(gdb) ptype t1
type = const int *
(gdb) ptype t2
type = const int *
(gdb) next
8 }
(gdb)
main () at 73526963.cpp:13
13 f<int>( &i, NULL );
(gdb) step
f<int> (t1=0xffffcbec, t2=0x0) at 73526963.cpp:7
7 return;
(gdb) ptype t1
type = const int *
(gdb) ptype t2
type = const int *
(gdb) next
8 }
(gdb)
main () at 73526963.cpp:15
15 float f1 = 20.22;
(gdb)
16 f<float>( &f1, NULL);
(gdb) step
f<float> (t1=0xffffcbe8, t2=0x0) at 73526963.cpp:7
7 return;
(gdb) ptype t1
type = const float *
(gdb) ptype t2
type = const float *
(gdb) next
8 }
(gdb)
main () at 73526963.cpp:17
17 return 0;
(gdb)
18 }
(gdb)
0x0000000180049b7d in _cygwin_exit_return () from /usr/bin/cygwin1.dll
(gdb)
Single stepping until exit from function _cygwin_exit_return,
which has no line number information.
[Thread 936.0x480 exited with code 0]
[Thread 936.0x474 exited with code 0]
[Thread 936.0x2024 exited with code 0]
[Thread 936.0x634 exited with code 0]
[Inferior 1 (process 936) exited normally]
(gdb) quit
$ # We can use b/break or stop in or stop at or step or s or next or n or continue or c based on related available debugger at current OS.
*/
I can get more debug info if built my program on Windows compared to Linux.
Here is my code:
#include <iostream>
#include <vector>
using namespace std;
class Base
{
public:
Base() = default;
virtual ~Base() = default;
};
class Derived : public Base
{
public:
Derived() = default;
~Derived() = default;
private:
int i = 1;
};
int main()
{
vector<Base*> a;
a.push_back(new Derived());
return 0;
}
Build On Linux:
Build On Windows:
It's obvious I can get more information with Windows build version. Such as vector info, vector element real type, derived object info... But Linux version, I only get the pointer address. By the way, they are all debugging by visual studio. Is there some way to add more debug info to the program built by GNU compiler? Such as compiler flags?
I don't use visual studio, so not sure how you will make use of this answer from within that environment, however, I think you can get what you want using the GDB setting: set print object on.
To show this in action, here's my GDB (12.1) session, using the same test program that you posted:
$ gdb -q vec.x
Reading symbols from vec.x...
(gdb) b 26
Breakpoint 1 at 0x401245: file vec.cc, line 26.
(gdb) r
Starting program: /tmp/vec.x
Breakpoint 1, main () at vec.cc:26
26 return 0;
(gdb) p a
$1 = std::vector of length 1, capacity 1 = {0x418eb0}
(gdb) p a[0]
$2 = (Base *) 0x418eb0
(gdb) p *a[0]
$3 = {
_vptr.Base = 0x403040 <vtable for Derived+16>
}
(gdb) set print object on
(gdb) p a[0]
$4 = (Derived *) 0x418eb0
(gdb) p *a[0]
$5 = (Derived) {
<Base> = {
_vptr.Base = 0x403040 <vtable for Derived+16>
},
members of Derived:
i = 1
}
(gdb) q
I fixed this problem by add a init command to the ~/.gdbinit.
Add the following command to the first line of file ~/.gdbinit.
set print object on
I'm trying to print the return value of a templated member function in gdb (version 7.6.1 I think) of an rvalue reference, so what I write in gdb amounts to something like this:
gdb> print (*(TypeOne*)var).get<TypeTwo>()
I've tried parenthesizing various parts of the expression with no success, and I wasnt able to find any other question on this. Anyone know?
Starting from this related post: How to `print`/evaluate c++ template functions in gdb
I was able to figure out how to do this within my own program.
I'm not using an rvalue nor a variant so it may not work for that, but I think it's still relevant to this question.
My use case was a method with a single enum as a template parameter, similar to this:
#include <stdio.h>
enum class MyEnum {
VALUE_0 = 0,
VALUE_1 = 1
};
struct TestStruct {
template <MyEnum VALUE>
int getValue() {
if constexpr (VALUE == MyEnum::VALUE_0) {
return value_0;
} else /* VALUE == MyEnum::VALUE_1 */ {
return value_1;
}
}
const int value_0 = 7;
const int value_1 = 9;
};
int main()
{
TestStruct test;
test.template getValue<MyEnum::VALUE_0>();
test.template getValue<MyEnum::VALUE_1>();
return 0;
}
If we use ptype on the object we get a list of methods on the object:
(gdb) b 36
Breakpoint 1 at 0x4004f7: file main.cpp, line 36.
(gdb) r
Starting program: /home/a.out
Breakpoint 1, main () at main.cpp:36
36 return 0;
(gdb) ptype test
type = struct TestStruct {
const int value_0;
const int value_1;
public:
int getValue<(MyEnum)1>(void);
int getValue<(MyEnum)0>(void);
}
If we want to call this method:
int getValue<(MyEnum)1>(void);
We can call it by using the name exactly as shown, in single quotes.
(gdb) p test.'getValue<(MyEnum)1>'()
$1 = 9
You can try it here: https://onlinegdb.com/7OtaUvK3g
Note from the other thread:
Without an explicit instance in the source code, the compiler will treat the template code as it would "static inline" code and optimize it out if it is unused.
So you must call the method somewhere in your code to be able to call it in gdb at all, this will not work otherwise.
Consider the following program, which I compile with g++ -g myprog.cc.
#include<iostream>
struct Context {
//char *s; // version 1
std::string s; // version 2
};
void f(Context);
void f(Context c) {}
int main(void) {
Context c = Context();
f(c);
}
Version 1 has a char * member, while version 2 replaces it with std::string.
Using gdb, I step through the code and get this:
Temporary breakpoint 1, main () at myprog.cc:12
12 Context c = Context();
&ebsp;Missing separate debuginfos, use: debuginfo-install libgcc-4.4.7-11.el6.x86_64 libstdc++-4.4.7-11.el6.x86_64
(gdb) s
13 f(c);
(gdb) s
f (c=...) at myprog.cc:9
9 void f(Context c) {}
(gdb) s
main () at myprog.cc:14
14 }
Nothing wrong here.
If I step through version 2, I get:
Temporary breakpoint 1, main () at myprog.cc:12
12 Context c = Context();
Missing separate debuginfos, use: debuginfo-install libgcc-4.4.7-11.el6.x86_64 libstdc++-4.4.7-11.el6.x86_64
(gdb) s
Context::Context (this=0x7fffffffe400) at myprog.cc:3
3 struct Context {
(gdb) s
main () at myprog.cc:13
13 f(c);
(gdb) s
Context::Context (this=0x7fffffffe410) at myprog.cc:3
3 struct Context {
(gdb) s
f (c=...) at myprog.cc:9
9 void f(Context c) {}
(gdb) s
Context::~Context (this=0x7fffffffe410, __in_chrg=) at myprog.cc:3
3 struct Context {
(gdb) s
Context::~Context (this=0x7fffffffe400, __in_chrg=) at myprog.cc:3
3 struct Context {
(gdb) s
main () at myprog.cc:14
14 }
Why is it that when I pass in a struct Context with the std::string member, I get the output Context::Context (this=0x7fffffffe400)?
Also, when I instantiate the struct, this=0x7fffffffe400. When I pass it in, this=0x7fffffffe410. Why is that?
You pass c by value to a function that doesn't do anything. So the compiler has to produce any visible effects of pass by value semantics. The compiler can't be sure that copying and then destroying the string has no consequences, so it does it. It can be sure that copying a char * and destroying the copy has no consequences, so it doesn't bother.
What's happening is you're seeing the compiler generated constructor, which is not generated for the struct with just a pointer, because there would be nothing to do in that constructor. For the struct with the std::string member, it likely calls std::strings constructor.
Since the constructor is a non-static member function, the this=0x7fffffffe400 is the implicit 'this' pointer argument being passed in.
This question already has answers here:
Why gdb casting is not working?
(4 answers)
Closed 6 years ago.
From this link
gdb interpret memory address as an object
we know that, if an object of class type A is at a specific address such as 0x6cf010, then we can use:
(gdb) p *(A *) 0x6cf010
to print the member elements of this object.
However, this seems doesn't work when c++ namespace is involved. That is, if the object of class type A::B, then all the following trying doesn't work:
(gdb) p *(A::B *) 0x6cf010
(gdb) p *((A::B *) 0x6cf010)
So, who knows how to print the object elements under this conditions?
We can use the following deliberate core code to try to print the members of p from the address (we can use "info locals" to show the address).
#include <stdio.h>
namespace A
{
class B
{
public:
B(int a) : m_a(a) {}
void print()
{
printf("m_a is %d\n", m_a);
}
private:
int m_a;
};
}
int main()
{
A::B *p = new A::B(100);
p->print();
int *q = 0;
// Generating a core here
*q = 0;
return 0;
}
I know that this is labeled as answered, but I was able to reproduce this problem using gdb on OS X (GNU gdb 6.3.50-20050815 (Apple version gdb-1820) (Sat Jun 16 02:40:11 UTC 2012)) and the works-for-me solution didn't answer it for me.
Turns out there was another question on SO that did have an answer which worked, so I think it's worth pulling into this quesiton:
Why gdb casting is not working?
The short answer is that you may have to single-quote your namespaced variables:
(gdb) p ('MyScope::MyClass'*) ptr;
Works for me:
g++ -g test.cpp -o test
gdb test
(gdb) break main
(gdb) r
Breakpoint 1, main () at test.cpp:22
22 A::B *p = new A::B(100);
(gdb) n
24 p->print();
(gdb) n
m_a is 100
26 int *q = 0;
(gdb) p p
$1 = (A::B *) 0x602010
(gdb) p (A::B *) 0x602010
$2 = (A::B *) 0x602010
(gdb) p *((A::B *) 0x602010)
$3 = {m_a = 100}
It works for me. What are you using (gcc version, OS, compilation flags?)