Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does backtrace work?

Tags:

c++

linux

gdb

#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;
}
like image 832
Aquarius_Girl Avatar asked Jan 30 '12 05:01

Aquarius_Girl


2 Answers

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.

like image 147
Mike Seymour Avatar answered Oct 05 '22 04:10

Mike Seymour


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.

like image 42
David Schwartz Avatar answered Oct 05 '22 05:10

David Schwartz