use*_*096 44 c++ types gdb instanceof superclass
我正在用GDB调试一个C++程序.
我有一个指向某个类的对象的指针.指针被声明为某些超类,它由几个子类扩展.
对象中没有字段指定此对象的精确类类型,但是定义了一些虚函数(例如bool is_xxx())以在运行时告知类类型.
有没有办法在不调用这些虚函数的情况下告诉GDB中对象的精确类类型.当程序是多线程的时,在GDB中调用这些函数可能会产生令人困惑的结果.
Bet*_*eta 52
使用ptype.如果您单独使用它,则获得指针的声明类型:
(gdb) ptype ptr
type = class SuperClass {
// various members
} *
Run Code Online (Sandbox Code Playgroud)
要获取指向的对象的实际类型,请设置"print object"变量:
(gdb) set print object on
(gdb) ptype ptr
type = /* real type = DerivedClass * */
class SuperClass {
// various members
} *
Run Code Online (Sandbox Code Playgroud)
Joa*_*him 16
在我的系统上,ptype或whatis也只是显示出明显的.
(gdb) whatis pObject
type = QObject *
Run Code Online (Sandbox Code Playgroud)
但打印vtable的第一个条目帮助我:
(gdb) p /a (*(void ***)pObject)[0]
$4 = 0xb4b4cdf4 <QMessageBox::metaObject() const>
Run Code Online (Sandbox Code Playgroud)
这里pObject指向一个从QObject派生的QMessageBox.仅当vtable-entry指向由派生类重写的方法时,此方法才有效.
另请参阅: 使用GDB打印C++ vtable
编辑:仅打印指向vtable的指针更可靠(尽管输出使用了损坏的名称并且不那么可读):
(gdb) p /a (*(void ***)pObject)
$5 = 0xb4af33a0 <_ZTV11QMessageBox+8>
Run Code Online (Sandbox Code Playgroud)
GDB 7.11
从GDB 7.11,GCC 5.3.1,Ubuntu 16.04开始,仅执行以下操作:
p *myBase
Run Code Online (Sandbox Code Playgroud)
关于编译的东西:
gcc -O0 -ggdb3
Run Code Online (Sandbox Code Playgroud)
可能就足够了,因为它已经显示:
$1 = {_vptr.MyBase = 0x400c00 <vtable for MyDerived1+16>}
Run Code Online (Sandbox Code Playgroud)
MyDerived1我们正在寻找的当前派生类在哪里.
但如果你这样做:
set print object on
Run Code Online (Sandbox Code Playgroud)
输出更清晰,看起来像:
$1 = (MyDerived1) {<MyBase> = {_vptr.MyBase = 0x400c00 <vtable for MyDerived1+16>}, <No data fields>}
Run Code Online (Sandbox Code Playgroud)
这也会影响其他命令:
ptype myBase
Run Code Online (Sandbox Code Playgroud)
这表现了:
type = /* real type = MyDerived1 * */
class MyBase {
public:
virtual int myMethod(void);
} *
Run Code Online (Sandbox Code Playgroud)
代替:
type = class MyBase {
public:
virtual int myMethod(void);
} *
Run Code Online (Sandbox Code Playgroud)
在这种情况下,没有指示派生类型set print object on.
whatis 同样受到影响:
(gdb) whatis myBase
type = MyBase *
(gdb) set print object on
(gdb) whatis myBase
type = /* real type = MyDerived1 * */
MyBase *
Run Code Online (Sandbox Code Playgroud)
测试程序:
#include <iostream>
class MyBase {
public:
virtual int myMethod() = 0;
};
class MyDerived1 : public MyBase {
public:
virtual int myMethod() { return 1; }
};
class MyDerived2 : public MyBase {
public:
virtual int myMethod() { return 2; }
};
int main() {
MyBase *myBase;
MyDerived1 myDerived1;
MyDerived2 myDerived2;
myBase = &myDerived1;
std::cout << myBase->myMethod() << std::endl;
myBase = &myDerived2;
std::cout << myBase->myMethod() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17249 次 |
| 最近记录: |