1. 程式人生 > >獲取C++虛函數表地址和虛函數地址

獲取C++虛函數表地址和虛函數地址

rtu 虛函數地址 cpp 32位 對象 知識點 cout virt def

1.先介紹C++類的內存結構,大家可以看以下博客,覺得不錯

  https://blog.csdn.net/fenxinzi557/article/details/51995911

  其中和本次相關的知識點是一個有虛函數的類的前4個字節是指向虛函數表首地址的指針_vfptr

2.下面開始說具體的求解過程

class  AA {  
public:  
    virtual void func1() { cout << "AA ::func1" << endl; }  
    virtual void func2() { cout << "AA ::func2" << endl; }  
    void func3() { cout << "AA::func3" << endl; }  
};  
  
typedef void(*Fun)(void);  //函數指針  
int main()  
{  
    AA a;  
    //  *****printf("虛表地址:%p\n", *(int *)&a); 解析*****:  
    //  1.&a代表對象a的起始地址  
    //  2.(int *)&a 強轉成int *類型,為了後面取a對象的前四個字節,前四個字節是虛表指針  
    //  3.*(int *)&a 取前四個字節,即vptr虛表地址  
    
  
    //  *****printf("第一個虛函數地址:%p\n", *(int *)*(int *)&a);*****:  
    //  根據上面的解析我們知道*(int *)&a是vfptr,即虛表指針.並且虛表是存放虛函數指針的  
    //  所以虛表中每個元素(虛函數指針)在32位編譯器下是4個字節,因此(int *)*(int *)&a 
    //  這樣強轉後為了後面的取四個字節.所以*(int *)*(int *)&a就是虛表的第一個元素.  
    //  即f()的地址.  
    //  那麽接下來的取第二個虛函數地址也就依次類推.  始終記著vfptr指向的是一塊內存,  
    //  這塊內存存放著虛函數地址,這塊內存就是我們所說的虛表.  
    //  
    printf("虛表地址:%p\n", *(int *)&a);  
    printf("第一個虛函數地址:%p\n", *(int *)*(int *)&a);  
    printf("第二個虛函數地址:%p\n", *((int *)*(int *)(&a) + 1));  
  
    Fun pfun = (Fun)*((int *)*(int *)(&a));  //virtual func1();  
    printf("func1():%p\n", pfun);  
    pfun();  
  
    pfun = (Fun)(*((int *)*(int *)(&a) + 1));  //virtual func2();  
    printf("func2():%p\n", pfun);  
    pfun();  
  
}  

  

獲取C++虛函數表地址和虛函數地址