回溯如何工作?

Aqu*_*irl 5 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;
}
Run Code Online (Sandbox Code Playgroud)

回溯输出:

(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) 
Run Code Online (Sandbox Code Playgroud)

问题:

  • 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...)
Run Code Online (Sandbox Code Playgroud)
  • 上面的输出什么也没显示,因为被调用函数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
Run Code Online (Sandbox Code Playgroud)
  • 第 1 帧和第 2 帧准确显示什么?

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

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

编写以下代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*our 4

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

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

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

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

已为该对象分配了空间(在本地堆栈帧中);它只是还没有初始化。你会看到那个空间中发生的任何事情,{x = 0}如果你跨过初始化线,它就会变成这样。

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

它什么也不显示,因为你要求它什么都不显示;的参数bt指定要显示的堆栈帧数,而您说的是零。

第 1 帧和第 2 帧到底显示了什么?

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

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

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

obj1.x每个都是不同对象(和)的成员obj2.x,并且都没有被初始化;所以每个都显示了恰好位于该内存位置的一些随机值。同样,如果您跳过初始化器,两者都将变为零。