2011-10-06 52 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

相關問題