c++ gdb可以显示被析构的变量吗?

dfddblmv  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(127)

示例:

#include <assert.h>

int v = 0;

struct Foo {
    Foo() { ++v; }
    ~Foo()
    {
        --v;
        assert(v != 1); // artificially stop the debugger here
    }
};

int main()
{
    Foo a; // assert in destructor here?
    Foo b; // assert in destructor here?
    Foo c; // assert in destructor here?
    return 0;
} // main()

我想调试器应该能够告诉我Foo的哪一行/哪一个示例在Assert,但它只显示它正在退出main()的作用域:

#6  0x00007ffff7d9ee96 in __GI___assert_fail (assertion=0x555555556019 "v != 1", file=0x555555556010 "main.cpp", line=8, 
    function=0x555555556004 "Foo::~Foo()") at ./assert/assert.c:101
#7  0x000055555555521c in Foo::~Foo (this=<optimized out>, __in_chrg=<optimized out>) at main.cpp:8
#8  0x00005555555551b6 in main () at main.cpp:17
(gdb) f 8
#8  0x00005555555551b6 in main () at main.cpp:17
17      } // main()
    • 我知道罪魁祸首是b,但如何才能让gcc告诉我?**

这仅仅是一个缺失的特性,还是有更基本的东西阻止调试器显示这些信息?
如果我为每个示例添加一个作用域,它就会变得很清楚,但我不认为我应该重新编译。

int main()
{
    Foo a;
    {
        Foo b;
        {
            Foo c;
        }
    } // <-- backtrace of the assert shows this line
    return 0;
}

类的成员也存在同样的问题:

class Bar {
    Foo a;
    Foo b;
    Foo c;
};

[EDIT]我真正希望看到的是调试器从main()返回时返回到Foo c;所在的行,然后返回到Foo b;等。就像下面的示例中发生的情况一样,调试器在最终进入func()之前一次遍历一行Baz()。

func(Baz(),
         Baz(),
         Baz());
iezvtpos

iezvtpos1#

但是我怎么才能让gcc告诉我呢?
你不能(至少不能直接)--它不知道你对此感兴趣,但是你可以给予Foo的每个示例一个名字,它在构造函数和析构函数中打印this的值和名字。
您也可以从广发银行获得以下信息:

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007ffff7e55d2f in __pthread_kill_internal (signo=<optimized out>, threadid=<optimized out>) at ./nptl/pthread_kill.c:89
#2  __GI___pthread_kill (threadid=<optimized out>, signo=<optimized out>) at ./nptl/pthread_kill.c:89
#3  0x00007ffff7f9ee70 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x00007ffff7df1472 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff7df1395 in __assert_fail_base (fmt=<optimized out>, assertion=<optimized out>, file=<optimized out>, line=<optimized out>, function=<optimized out>) at ./assert/assert.c:92
#6  0x00007ffff7dffdf2 in __GI___assert_fail (assertion=0x555555556015 "v != 1", file=0x555555556010 "t.cc", line=10, function=0x555555556004 "Foo::~Foo()") at ./assert/assert.c:101
#7  0x0000555555555200 in Foo::~Foo (this=0x7fffffffd81e, __in_chrg=<optimized out>) at t.cc:10
#8  0x0000555555555183 in main () at t.cc:20

(gdb) fr 8
#8  0x0000555555555183 in main () at t.cc:20
20      } // main()
(gdb) info locals
a = {<No data fields>}
b = {<No data fields>}
c = {<No data fields>}
(gdb) p &a
$1 = (Foo *) 0x7fffffffd81f
(gdb) p &b
$2 = (Foo *) 0x7fffffffd81e   <<=== match for this in frame 7

当然,这要求this没有优化(因为它在堆栈中),* 或者 * 在析构函数中打印this的值。
[EDIT]我真正想看到的是调试器返回到Fooc所在的行;当它从main()返回时,取Foo B;等等。
理论上,编译器 * 可以 * 做到这一点,但是(我怀疑)这会让大多数最终用户非常困惑:“当我只是构造Foo时,为什么调用 * 析构函数 *?"。

相关问题