debugging 我如何获得正确的“this”ptr信息为GDB函数断点可用于条件断点?

beq87vna  于 2023-05-23  发布在  其他
关注(0)|答案(1)|浏览(165)

我想在一个C++构造函数、析构函数或方法上设置断点,并查看调用它的对象的正确的“this”指针。
不幸的是,当断点命中时,GDB声明的“this”信息不是预期的信息。如果构造函数、析构函数或方法至少包含一行,并且在命中断点后使用单步执行一次,则“this”信息似乎发生了变化,然后显示预期值。
然而

  • 构造函数、析构函数或方法也可以为空(或在前两种情况下设置为默认值),因此单步执行可能不可行。
  • 也不可能开箱即用地配置要在命中执行单步的断点时执行的命令,然后继续正常执行,因为“单步”或“下一个”命令会中断所提供的命令序列的进一步执行,从而阻止“继续”语句的执行
  • 我还相信,由于“this”值最初是错误的,因此很可能无法设置条件断点,并且仅在调用地址已知的对象时才停止(=应该在“this”指针中)。

简单的示例代码MyClass.cpp:

#include <iostream>

class MyClass
{
public:
    MyClass() {
        std::cout << "MyClass() constructor, this = " << this << std::endl;
    }

    void someMethod() {
        std::cout << "someMethod(), this = " << this << std::endl;
    }

    ~MyClass() {
        std::cout << "MyClass() destructor, this = " << this << std::endl;
    }
};

int
main(int argc, char **argv)
{
    MyClass *myClass = new MyClass();
    std::cout << "MyClass located at = " << myClass << std::endl;
    myClass->someMethod();
    delete myClass;
}

编译完成

g++ -std=c++14 -g  -o MyClass MyClass.cpp

使用GDB执行:

$ gdb ./MyClass
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
...
Reading symbols from ./MyClass...
(gdb) b MyClass::MyClass
Breakpoint 1 at 0x1352: file MyClass.cpp, line 6.
(gdb) b MyClass::~MyClass
Breakpoint 2 at 0x13ee: file MyClass.cpp, line 14.
(gdb) b MyClass::someMethod
Breakpoint 3 at 0x13a0: file MyClass.cpp, line 10.
(gdb) b 11
Breakpoint 4 at 0x13b0: file MyClass.cpp, line 11.
(gdb) r
Starting program: /home/ostkamp/src/cpp_examples/MyClass 

Breakpoint 1, MyClass::MyClass (this=0x7ffff7e7bb39 <operator new(unsigned long)+25>) at MyClass.cpp:6
6       MyClass() {
(gdb) c
Continuing.
MyClass() constructor, this = 0x55555556aeb0
MyClass located at = 0x55555556aeb0

Breakpoint 3, MyClass::someMethod (this=0x7ffff7f037a3 <std::ostream::flush()+35>) at MyClass.cpp:10
10      void someMethod() {
(gdb) c
Continuing.

Breakpoint 4, MyClass::someMethod (this=0x55555556aeb0) at MyClass.cpp:11
11          std::cout << "someMethod(), this = " << this << std::endl;
(gdb) c
Continuing.
someMethod(), this = 0x55555556aeb0

Breakpoint 2, MyClass::~MyClass (this=0x55555556aeb0, __in_chrg=<optimized out>) at MyClass.cpp:14
14      ~MyClass() {
(gdb) c
Continuing.
MyClass() destructor, this = 0x55555556aeb0
[Inferior 1 (process 9105) exited normally]
(gdb)

可以看出,构造函数(第6行)和someMethod(第10行)的断点显示了无效的“this”信息。someMethod中的断点(第11行)显示了正确的"this"。有时这也适用于析构函数(第14行)。
有没有办法得到正确的“这个”信息?
有没有办法设置一个条件断点,例如:for someMethod()调用,仅当执行具有已知地址的对象时才命中,例如这里的0x55555556aeb0不使用内部的一行方法?

whlutmcx

whlutmcx1#

不幸的是,当断点命中时,GDB声明的“this”信息不是预期的信息。
你有一个bug的GCC或GDB。
以下是我所看到的:

(gdb) b MyClass::MyClass
Breakpoint 1 at 0x12e8: file foo.cc, line 7.
(gdb) b MyClass::someMethod
Breakpoint 2 at 0x1334: file foo.cc, line 11.
(gdb) b MyClass::~MyClass
Breakpoint 3 at 0x1380: file foo.cc, line 15.
(gdb) run
Starting program: /tmp/a.out

Breakpoint 1, MyClass::MyClass (this=0x55555556aeb0) at foo.cc:7
7               std::cout << "MyClass() constructor, this = " << this << std::endl;
(gdb) c
Continuing.
MyClass() constructor, this = 0x55555556aeb0
MyClass located at = 0x55555556aeb0

Breakpoint 2, MyClass::someMethod (this=0x55555556aeb0) at foo.cc:11
11              std::cout << "someMethod(), this = " << this << std::endl;
(gdb) c
Continuing.
someMethod(), this = 0x55555556aeb0

Breakpoint 3, MyClass::~MyClass (this=0x55555556aeb0, __in_chrg=<optimized out>) at foo.cc:15
15              std::cout << "MyClass() destructor, this = " << this << std::endl;
(gdb) c
Continuing.
MyClass() destructor, this = 0x55555556aeb0
[Inferior 1 (process 434310) exited normally]

这是使用gcc (Debian 12.2.0-14) 12.2.0和相应的GDB。
this GDB bug可能是导致问题的原因。this answer
如果您的x/4i 0x13eeendbr64开头,那么几乎可以肯定这就是问题所在。
好消息是,构建和使用更新的GDB非常容易:只需获取一个新版本,然后运行./configure && make && make install

相关问题