#include <iostream>
using namespace std;
class dummyA
{
int x;
public:
dummyA ()
{
x = 0;
}
void test ()
{
x++;
}
};
int main ()
{
cout << "\nG'Morning";
dummyA obj;
obj.test ();
return 0;
}
The backtrace output:
(gdb) bt
#0 main () at backtrace.cpp:21
(gdb) bt full
#0 main () at backtrace.cpp:21
obj = {x = -8896}
(gdb) n
22 dummyA obj;
(gdb)
Questions:
bt is said to be printing a backtrace of the entire stack: one line per frame for all frames in the stack, but I see only the name of the function in the output? Why is that so?
bt full shows the inner works, how can it read the 'obj' when the control is not on that line (dummyA obj;) yet?
EDIT 1:
Breakpoint 1, dummyA::testB (this=0x7fffffffdc50) at backtrace.cpp:20
20 x = x + 2;
(gdb) bt 0
(More stack frames follow...)
The above output shows nothing because the callee function testB has zero local variables? Is that correct?
(gdb) bt 1
#0 dummyA::testB (this=0x7fffffffdc50) at backtrace.cpp:20
(More stack frames follow...)
(gdb) bt 2
#0 dummyA::testB (this=0x7fffffffdc50) at backtrace.cpp:20
#1 0x000000000040078b in main () at backtrace.cpp:31
What do frames 1 and 2 show exactly?
(gdb) bt full
#0 main () at backtrace.cpp:26
obj1 = {x = -8896}
obj2 = {x = 0}
Why does x have two different values here, assuming that the breakpoint is on main?
WRT the following code:
#include <iostream>
using namespace std;
class dummyA
{
int x;
public:
dummyA ()
{
x = 0;
}
void testA ()
{
x = x + 1;
}
void testB ()
{
x = x + 2;
}
};
int main ()
{
cout << "\nG'Morning";
dummyA obj1;
dummyA obj2;
obj1.testA ();
obj1.testB ();
obj2.testA ();
obj2.testB ();
return 0;
}
bt is said to be printing a backtrace of the entire stack: one line per frame for all frames in the stack, but I see only the name of the function in the output? Why is that so?
The backtrace shows the current function, then the function that called that, and so on, all the way back to main(). Each "stack frame" is the section of stack used by a particular function, so there's one frame per function. Since the current function is main(), there is only one frame to show.
(Perhaps you were hoping the the backtrace would allow you to see every line of code that was executed. Unfortunately, when running code normally (which is what gdb does, apart from adding breakpoints), there isn't enough available information to do that; the best you can do is look at the history of function calls.)
bt full shows the inner works, how can it read the 'obj' when the control is not on that line (dummyA obj;) yet?
Space has been allocated (in the local stack frame) for the object; it just hasn't been initialised yet. You're seeing whatever happens to be in that space, and it should become {x = 0} if you step over the initialisation line.
The above output shows nothing because the callee function testB has zero local variables? Is that correct?
It shows nothing because you asked it to show nothing; the argument to bt specifies how many stack frames to show, and you said zero.
What do frames 1 and 2 show exactly?
In the first case, you asked for one stack frame; that of the current function. It tells you that you're in the function dummyA::testB, that the address of the object it was called on (this) is 0x7fffffffdc50, and that the corresponding source line is line 20 of backtrace.cpp.
In the second case, you asked for two frames, so it also shows where the current function was called from: the function main(), source line 31 of backtrace.cpp.
Why does x have two different values here, assuming that the breakpoint is on main?
Each is the member of a different object (obj1.x and obj2.x), and neither has been initialised; so each is showing some random value that happens to be in that memory location. Again, both will become zero if you step over the initialisers.
The object has not been constructed yet, but space has been allocated for it. You're seeing the entire backtrace -- you're in main, period.
Related
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
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.
I have a problem with compiling some code for mingw32, linking a mingw32-compiled library. When I call a member function (i.e. constructor) of a class in the library that I am dynamically linking to, the arguments are pushed onto the stack in the wrong order.
Here's an example:
Program received signal SIGSEGV, Segmentation fault.
0x65e717e9 in TCODMap::TCODMap (this=0x40, width=48, height=40)
at src/fov.cpp:28
28 src/fov.cpp: No such file or directory.
(gdb) backtrace
#0 0x65e717e9 in TCODMap::TCODMap (this=0x40, width=48, height=40)
at src/fov.cpp:28
#1 0x00401bda in map::map (this=0x8683c8, dim=..., fill=0 '\000')
at src/map.cpp:12
#2 0x004017d7 in next_init () at src/main.cpp:24
#3 0x00401b8e in main (argc=1, argv=0x862fc8) at src/main.cpp:98
My call to the TCODMap constructor has the arguments width=64 and height=48, however notably the this implicit argument is set to 64 (0x40), the width is set to 48, and the height is set to some garbage value 40. In this case, the constructor is called as part of an initializer for another class that I have in my user code.
The code in question:
map::map(loc dim, uint8 fill) : _dim(dim), tcodmap(_dim.x, _dim.y), actors()
{
_size = _dim.x * _dim.y;
_data = new uint8[_size];
for (int xi = 0; xi < _dim.x; xi++)
{
for (int yi = 0; yi < _dim.y; yi++)
{
put(xi, yi, fill);
}
}
}
It seems the thiscall calling convention, which says the this pointer should be pushed last onto the stack such that it is lexically first in the argument list, is not being obeyed correctly.
How do I fix this?
I wrote a test program to check what you trying to do. 1st of all you are getting the error at run time and not at compile time as you have provided a stack trace of gdb.
#include <iostream>
struct Data{
int _x;
int _y;
};
class A{
public:
A(){}
A(int x){}
A(const A&,int y){}
A(int x , int y)
{
}
};
class B{
Data _d;
A _a;
public:
B(Data d,int fill):_d(d),_a(_d._x,_d._y)
{
}
};
int main()
{
Data d;
d._x=1;
d._y=2;
B instance(d,4);
return 0;
}
Stacktrace:
> Breakpoint 1, B::B (this=0x7fffffffe1a0, d=..., fill=4) at this.cpp:26
> 26 B(Data d,int fill):_d(d),_a(_d._x,_d._y) (gdb) s A::A
> (this=0x7fffffffe1a8, x=1, y=2) at this.cpp:17 17 } (gdb) bt
> #0 A::A (this=0x7fffffffe1a8, x=1, y=2) at this.cpp:17
> #1 0x00000000004006fb in B::B (this=0x7fffffffe1a0, d=..., fill=4)
> at this.cpp:26
> #2 0x0000000000400652 in main () at this.cpp:39
Point here is that the 'this' implicit pointer would point to a valid address until unless your program is causing "stack buffer overflow" which corrupts the memory assigned to 'this' pointer for tcodmap.
You should share more details of complete code, how you use this program.
Do you experince this issue at every run or is it random?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Here is the code
int& fun(){
static int x = 10;
return x;
}
int main() {
fun() = 30;
cout<< fun();
getch();
}
The output is 30.
How does this work?
Let's read it line by line:
int& fun()
declares a function named fun which returns a reference to an integer variable
{
static int x = 10;
The x variable is static inside this function. A special place in memory is reserved for it and is initialized with 10. Every time this function is called x will get the value stored in that special location.
return x;
}
We return x and leave the function. Let's go to the main one:
int main()
{
fun() = 30;
Remember that fun returns the reference to an int. Here we modify the integer to be 30. Since this integer has static allocation every time fun will be called from now on x will start with 30, unless other changes are made.
cout<< fun();
Since x is 30 that's what you get.
getch();
}
Suggestion: use GDB and trace the program's execution step-by step:
$ gdb ./a.out
(gdb) b main
Breakpoint 1 at 0x40077b: file 1.cpp, line 11.
(gdb) r
Starting program: /tmp/a.out
Breakpoint 1, main () at 1.cpp:11
11 fun() = 30;
We start GDB, set a breakpoint at the begining of main and start the program.
(gdb) disp fun()
1: fun() = (int &) #0x60104c: 10
Since fun returns a reference to a static variable I can display it's value at each step in GDB.
(gdb) s
fun () at 1.cpp:6
6 return x;
1: fun() = (int &) #0x60104c: 10
Running a single step we see that we are in func. This is the place where x is returned (as a reference) to be attributed 30.
(gdb) n
7 }
1: fun() = (int &) #0x60104c: 30
Indeed, after leaving the function, x is 30.
(gdb)
main () at 1.cpp:13
13 cout<< fun();
1: fun() = (int &) #0x60104c: 30
(gdb) s
fun () at 1.cpp:6
6 return x;
1: fun() = (int &) #0x60104c: 30
(gdb)
7 }
1: fun() = (int &) #0x60104c: 30
(gdb)
main () at 1.cpp:15
15 }
1: fun() = (int &) #0x60104c: 30
(gdb) q
We continue the program's execution and leave GDB (though your question is already answered).
It is straightforward : fun returns the reference to the static variable inside the function, which is assigned to 30 by this line:
fun() = 30;
this means, x inside the function is changed to 30. What is more? It is 30! You print it by calling again fun() in the next line.
Note that a static variable lives till the end of the program: it is not destroyed even if the function returns!
The fun function returns a reference-to an int type. This way, when you call fun() = 30, you actually set x to 30.
This way when you print it out, the fun function will no longer set it, cause that is a one-off declaration.
I defined a class named nth_best_parse this way:
class nth_best_parse {
public:
int traversal;
int nth_best_active;
int nth_best_passive;
double viterbi_prob;
nth_best_parse();
nth_best_parse(int t, int nbl, int nbr, double v) {traversal = t; nth_best_active = nbl; nth_best_passive = nbr; viterbi_prob = v;}
};
Then I declared vectors of this nth_best_parse as members of two different classes:
class Edge { // an edge associates an Earley style dotted-item with a span
public:
<some irrelevant stuff>
Span span; // Span of the edge
bool isActive;
vector<Traversal *> leading_traversals; // The list of traversals which lead to parsing of this edge
vector<nth_best_parse> n_best_parses;
union {
DottedRule rule_state; // Accessed if isActive is true
int symbol; // Accessed if isActive is false
// A symbol corresponding to the category of a passive edge
// Put inside this union to save space
};
inline int span_length() {return span.end - span.start;}
};
<some other stuff>
class BPCFGParser {
public:
// Some data structures used in intermediary computations for calculating the n-best parses
// vector<vector<int> > nth_best_pairs;
vector<vector<nth_best_parse> > n_best_pairs_for_traversals;
<some other stuff>
void compute_n_best_parses(Edge *e, int n);
<some other stuff>
}
Then I run this program with gdb (by the way, I'm using Linux Ubuntu 9.04, g++ 4.3.3,GNU gdb 6.8-debian) and set a breakpoint at the end of the definition of compute_n_best_parses() with some conditions (to locate the exact call of this function I wanted, I was tracing back from a segmentation fault). When gdb hit the breakpoint, I issued a set of commands and the gdb output was like this:
(gdb) print e->n_best_parses.size()
$27 = 1
(gdb) print e->n_best_parses[0]
$28 = (nth_best_parse &) #0x1e96240: {traversal = 0, nth_best_active = 0, nth_best_passive = 0, viterbi_prob = 0.16666666666666666}
(gdb) print e->n_best_parses[0].traversal
$29 = 0
(gdb) print &(e->n_best_parses[0].traversal)
$30 = (int *) 0x1e96240
(gdb) awatch *$30
Hardware access (read/write) watchpoint 6: *$30
(gdb) print e->n_best_parses
$31 = {<std::_Vector_base<nth_best_parse, std::allocator<nth_best_parse> >> = {
_M_impl = {<std::allocator<nth_best_parse>> = {<__gnu_cxx::new_allocator<nth_best_parse>> = {<No data fields>}, <No data fields>},
_M_start = 0x1e96240, _M_finish = 0x1e96258, _M_end_of_storage = 0x1e96288}}, <No data fields>}
(gdb) continue
Continuing.
Hardware access (read/write) watchpoint 6: *$30
Old value = 0
New value = 1
0x0000000000408a4c in __gnu_cxx::new_allocator<nth_best_parse>::construct<nth_best_parse> (this=0x1e96208, __p=0x1e96240, __args#0=#0x7fff8ad82260)
at /usr/include/c++/4.3/ext/new_allocator.h:114
114 { ::new((void *)__p) _Tp(std::forward<_Args>(__args)...); }
(gdb) backtrace
#0 0x0000000000408a4c in __gnu_cxx::new_allocator<nth_best_parse>::construct<nth_best_parse> (this=0x1e96208, __p=0x1e96240, __args#0=#0x7fff8ad82260)
at /usr/include/c++/4.3/ext/new_allocator.h:114
#1 0x000000000042169c in std::vector<nth_best_parse, std::allocator<nth_best_parse> >::push_back<nth_best_parse> (this=0x1e96208, __args#0=#0x7fff8ad82260)
at /usr/include/c++/4.3/bits/stl_vector.h:703
#2 0x0000000000402bef in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f5492858b78, n=3) at BPCFGParser.cpp:639
#3 0x00000000004027fd in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f5492859d58, n=3) at BPCFGParser.cpp:606
#4 0x00000000004027fd in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f549285a1d0, n=3) at BPCFGParser.cpp:606
#5 0x00000000004064d8 in main () at experiments.cpp:75
Line 639 of BPCFGParser.cpp was like this:
PUSH_BEST_PAIR_FOR_TRAVERSAL(i,row,column,grammar->probs[temp_rule.symbol][temp_rule.expansion]);
This was a macro defined at the beginning of the file as:
#define PUSH_BEST_PAIR_FOR_TRAVERSAL(x,y,z,t) n_best_pairs_for_traversals[x].push_back(nth_best_parse(x, y, z, e->leading_traversals[x]->active_edge->n_best_parses[y].viterbi_prob * e->leading_traversals[x]->passive_edge->n_best_parses[z].viterbi_prob * t))
By the way, class Traversal is defined as:
class Traversal { // Class for a traversal
public:
Edge *active_edge;
Edge *passive_edge;
Traversal();
Traversal(Edge *a, Edge *p) {active_edge = a; passive_edge = p;}
};
So actually I'm pushing something to the vector n_best_pairs_for_traversals, which is a member of an instance of the class BPCFGParser and the push_back() code somehow overwrites on the vector n_best_parses, which is a member of an instance of the class Edge. How can this ever be possible?
You obviously have memory corruption problems somewhere.
BUT there is not enough here information to help you.
But you are writing C++ code and your class contain pointers.
This is not a good sign (there should hardly ever be a RAW pointer in a C++ class).
This is also often the cause of memory corruption for inexperienced C++ developers!
Have you obeyed the rule of 4?
Make sure every class that contains RAW owned pointers:
constructor
copy constructor
assignment operator
destructor.
Are you sure you're passing a valid first argument to your macro? Maybe you're accessing out of bounds when doing n_best_pairs_for_traversals[x] because x is larger than the vector size.
I'd guess that you are using a vector to store objects (perhaps Traversal?), not realizing that pushing new elements onto that vector can invalidate pointers to elements already in the vector. Use a deque instead if this is the case.