如何确定一个对象是否是从GDB的一个指向基类的指针派生的C ++类的实例?

我正在用GDBdebugging一个C ++程序。

我有一个指向某个类的对象的指针。 指针被声明为一些超类,它被几个子类扩展。

在对象中没有字段来指定这个对象的精确类的types,但是一些虚函数(例如bool is_xxx())被定义为在运行时告诉类的types。

有没有一些方法可以在不调用这些虚函数的情况下告诉GDB中对象的精确类的types。 在GDB中调用这样的函数可能会在程序是multithreading时产生混乱的结果。

使用ptype 。 如果你自己使用它,你会得到指针的声明types:

 (gdb) ptype ptr type = class SuperClass { // various members } * 

要获得指向的对象的实际types,请设置“打印对象”variables:

 (gdb) set print object on (gdb) ptype ptr type = /* real type = DerivedClass * */ class SuperClass { // various members } * 

在我的系统ptype或什么也只显示明显。

 (gdb) whatis pObject type = QObject * 

但是打印vtable的第一个入口帮助了我:

 (gdb) p /a (*(void ***)pObject)[0] $4 = 0xb4b4cdf4 <QMessageBox::metaObject() const> 

这里的pObject指向从QObject派生的QMessageBox。 这只适用于如果vtable-entry指向由派生类覆盖的方法。

另请参阅: 使用GDB打印C ++ vtables

编辑:只打印指向vtable的指针工作更可靠(虽然输出使用了错位的名称,不太可读):

 (gdb) p /a (*(void ***)pObject) $5 = 0xb4af33a0 <_ZTV11QMessageBox+8> 

GDB 7.11

从GDB 7.11开始,GCC 5.3.1,Ubuntu 16.04,只做:

 p *myBase 

关于编译的东西:

 gcc -O0 -ggdb3 

可能已经足够,因为它已经显示:

 $1 = {_vptr.MyBase = 0x400c00 <vtable for MyDerived1+16>} 

MyDerived1是我们正在寻找的当前派生类。

但是,如果你另外做:

 set print object on 

输出更清晰,看起来像:

 $1 = (MyDerived1) {<MyBase> = {_vptr.MyBase = 0x400c00 <vtable for MyDerived1+16>}, <No data fields>} 

这也影响其他命令,如:

 ptype myBase 

这表明:

 type = /* real type = MyDerived1 * */ class MyBase { public: virtual int myMethod(void); } * 

代替:

 type = class MyBase { public: virtual int myMethod(void); } * 

在这种情况下,没有set print object on没有指示派生types。

whatis也同样受到影响:

 (gdb) whatis myBase type = MyBase * (gdb) set print object on (gdb) whatis myBase type = /* real type = MyDerived1 * */ MyBase * 

testing程序:

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

你不需要调用虚函数,你可以看到虚函数或虚表的地址。 另一种方法是使用RTTI