2011-10-06 182 views
4

我的一个C++程序中有一个有趣的问题。在程序执行过程中,我的某个类的vtable显得很乱。在gdb会话中,我发现如果我直接调用对象的方法,它会成功,但如果我使用指针或引用,则最终会导致完全不相关的类的析构函数,而这个类将不会很快实例化。没有this - 指针改变当然。如何在C++程序中查看gdb中的vtable?

假设我的观察结果是正确的,我该如何看gdb中的对象的vtable?我在使用gcc的Linux上,我的gdb版本是GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08

+0

我对此不是100%,所以我不会将它作为答案发布,但它应该足以查看'((void *)this)-1'(指针长度* *之前*这个')得到一个指向实际函数的指针(0终止的?)指针数组。他们不会携带方法名称或任何东西,但这确实是所有的虚拟表格。 – Blindy

+0

您是否使用Valgrind或任何类似的工具来分析您的代码? –

+0

你怎么知道你最终在一个不同的功能?你在调试或输出一些东西吗? –

回答

3

你可以使用gcc的-fdump-class-hierarchy选项,它会给你vtable的信息,但是输出可能非常冗长而难以阅读。

例如,给出下面的琐碎类:

class Base {                    
    public:                    
     virtual int method() = 0;              
};                      

class Derived : public Base {               
    public:                    
     int method() {                 
      return 10;                 
     }                    
}; 

相关的输出是

Vtable for Base 
Base::_ZTV4Base: 3u entries 
0  (int (*)(...))0 
8  (int (*)(...))(& _ZTI4Base) 
16 (int (*)(...))__cxa_pure_virtual 

Class Base 
    size=8 align=8 
    base size=8 base align=8 
Base (0x7f14c308ccc0) 0 nearly-empty 
    vptr=((& Base::_ZTV4Base) + 16u) 

Vtable for Derived 
Derived::_ZTV7Derived: 3u entries 
0  (int (*)(...))0 
8  (int (*)(...))(& _ZTI7Derived) 
16 (int (*)(...))Derived::method 

Class Derived 
    size=8 align=8 
    base size=8 base align=8 
Derived (0x7f14c2ee7208) 0 nearly-empty 
    vptr=((& Derived::_ZTV7Derived) + 16u) 
    Base (0x7f14c308cd20) 0 nearly-empty 
     primary-for Derived (0x7f14c2ee7208) 

这应该给你一个想法,地址范围debuggng等

+0

这和http://stackoverflow.com/questions/6191678/printc-vtables-using-gdb中的片段正是我所需要的。事实证明,一个'聪明'的功能对虚拟方法的对象来说并不好。谢谢。 –

+0

我会对“聪明”功能感兴趣。我喜欢破坏东西:) – bbtrb

0

期间预期除非你黑客入侵,否则我怀疑你的vtable变得混乱。你在调用costructor的虚函数吗?

也可能是调试器与您搞砸了。通过优化编译,您可能会得到相同地址的函数执行相同的操作,因为没有重复的代码。我在Windows下面遇到了这个问题,Visual Studio也在不同的函数中跳跃,这些函数实际上做了同样的事情。尝试输出一些东西,而不是用调试器遍历代码...这可能是

+0

后人注意:vtables可能会以各种方式搞砸。攻击vtable的“黑客攻击”通常会攻击OP可能试图压制的那类错误。一个好的经验法则是怀疑缓冲区溢出或免费使用。 – Wug