回溯是如何工作的?

时间:2012-01-30 05:49:58

标签: 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;
}

回溯输出:

(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) 

问题:

    据说
  • bt正在打印整个堆栈的回溯:堆栈中所有帧的每帧一行,但我只看到输出中函数的名称?为什么会这样?
  • bt full显示内部作品,当控件不在该行(dummyA obj;)时,如何读取'obj'?

编辑1:

Breakpoint 1, dummyA::testB (this=0x7fffffffdc50) at backtrace.cpp:20
20                              x = x + 2;
(gdb) bt 0
(More stack frames follow...)
  • 以上输出没有显示任何内容,因为被调用函数 testB 的局部变量为零?这是对的吗?
(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
  • 第1帧和第2帧的确切表现是什么?
  

(gdb)bt full
     backtrace.cpp中的#0 main():26
             obj1 = {x = -8896}
             obj2 = {x = 0}

  • 为什么x在这里有两个不同的值,假设断点在main?

WRT以下代码:

#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;
}

2 个答案:

答案 0 :(得分:2)

尚未构建对象,但已为其分配了空间。你看到整个回溯 - 你在main,期间。

答案 1 :(得分:2)

  据说

bt正在打印整个堆栈的回溯:堆栈中所有帧的每帧一行,但我只看到输出中函数的名称?为什么会这样?

回溯显示当前函数,然后是调用它的函数,依此类推,一直回到main()。每个“堆栈帧”是特定函数使用的堆栈部分,因此每个函数有一个帧。由于当前函数 main(),因此只显示一个框架。

(也许你希望回溯可以让你看到执行的每一行代码。不幸的是,当正常运行代码时(除了添加断点之外,这是gdb所做的),没有'足够的可用信息来做到这一点;你能做的最好的事情就是查看函数调用的历史。)

  

bt full显示内部作品,当控件不在该行(dummyA obj;)时,如何读取'obj'?

已为对象分配了空间(在本地堆栈帧中);它尚未初始化。您正在看到该空间中发生的任何事情,如果您跨过初始化线,它应该变为{x = 0}

  

上面的输出没有显示任何内容,因为被调用函数testB的局部变量为零?这是对的吗?

它没有显示任何内容,因为你要求它什么都不显示; bt的参数指定要显示的堆栈帧数,并表示为零。

  

第1帧和第2帧的确切显示是什么?

在第一种情况下,您要求一个堆栈帧;当前功能的那个。它告诉您,您在函数dummyA::testB中,它所调用的对象的地址(this)是0x7fffffffdc50,并且相应的源行是第20行backtrace.cpp

在第二种情况下,您要求两个帧,因此它还显示调用当前函数的位置:函数main()backtrace.cpp的源行31。

  

为什么x在这里有两个不同的值,假设断点在main?

每个都是不同对象(obj1.xobj2.x)的成员,并且都没有初始化;所以每个都显示一些恰好在该内存位置的随机值。如果你跨过初始化者,两者都将变为零。