青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

西城

指尖代碼,手上年華

聯(lián)系 聚合 管理
  20 Posts :: 0 Stories :: 62 Comments :: 0 Trackbacks
這兩天看了兩篇關(guān)于C++虛函數(shù)表的文章,一篇是陳浩的,http://blog.csdn.net/haoel/article/details/1948051
還有一篇是http://www.cnblogs.com/livingintruth/archive/2012/08/03/2620599.html。照著第二篇里的例子,
在我的電腦上測試了一下,發(fā)現(xiàn)有不少自己不懂的地方,原作者也沒有講的太清楚,所以自己查了不少資料,將一些所得
與大家分享。
示例的代碼(有部分改動):

#include <cstdio>
#include <iostream>
#include <typeinfo>
using namespace std;
class Point
{
public:
    Point()
    {
        cout<<"Point constructor"<<endl;
    }
  
    virtual void func_hs()
    {
        cout<<"Point::func_hs"<<endl;
        printf("the address of this --func_hs:%p\n",&Point::func_hs);
    }
    virtual void  func_zzy()
    {
        cout<<"Point::func_zzy"<<endl;
        printf("the address of this --func_zzy:%p\n",&Point::func_zzy);
    }

    static void print()
    {
        //相對地址,在虛表指針之后.0x4 0x8 0xc --------->point to member
        printf("&Point::x=%p\n&Point::y=%p\n&Point::z=%p\n",
               &Point::x,&Point::y,&Point::z);
    }

    void printThis()
    {
        //float *
        printf("&this->x=%p\n&this->y=%p\n&this->z=%p\n",
               &this->x,&this->y,&this->z);
    }

    void printVt()
    {
        printf("the address of object,this:%p\nthe address of vt:%p\n",
               this,(void*)*(int*)this);
    }
    void callVtFuncs(int num=2)
    {
        cout<<endl<<endl;
        
        typedef void (*Funp)(void);
        
        
        for(int i=0;i<num;i++)
        {
            Funp funp=(Funp)*((int*)*(int*)this+i);
            printf("%p\n",((int*)*(int*)this+i));
            printf("Point::callVtFuncs=>address of this fun:%p\n",funp);
            if(i==2||i==3)
            {
                continue;
            }
            funp();
        }
    }

    void printVirtualFunAddress()
    {
        cout<<endl<<endl;
           printf("func_hs:%p\nfunc_zzy:%p\nfunc_zzzy:%p\n",
              &Point::func_hs,&Point::func_zzy,
              &Point::func_zzzy);
        printf("%p\n",&Point::func_zzzy);
        
    }
    virtual ~Point()
    {
        // printf("%p\n",&Point::~Point);
        cout<<"Point destructor"<<endl;
    }
    virtual void  func_zzzy()
    {
        cout<<"Point::func_zzzy"<<endl;
        printf("the address of this --func_zzzy:%p\n",&Point::func_zzzy);
    }

protected:
    float x,y,z;
};

    
int main(int argc, char *argv[])
{
    Point point;
    Point::print();
    point.printThis();
    point.printVt();
    point.callVtFuncs(5);
    point.printVirtualFunAddress();
    printf("sizeof func:%u\n",sizeof(&main));
    printf("%p\n",&main);
    
    printf("sizeof memfunc:%u\n",sizeof(&Point::printVirtualFunAddress));
    printf("%p\n",&Point::printVirtualFunAddress);
    
    printf("%p\n",&Point::func_zzzy);

    printf("sizeof virtmemfunc:%u\n",sizeof(&Point::func_zzzy));
    cout<<typeid(point).name()<<endl;
    
    return 0;
}


Point類里面包括virtual desctructor共有4個virtual functions.
輸出結(jié)果如下:

Point constructor
&Point::x=0x4
&Point::y=0x8
&Point::z=0xc
&this->x=0xbffff624
&this->y=0xbffff628
&this->z=0xbffff62c
the address of object,this:0xbffff620
the address of vt:0x8048fc0


0x8048fc0
Point::callVtFuncs=>address of this fun:0x8048a12
Point::func_hs
the address of this --func_hs:0x1
0x8048fc4
Point::callVtFuncs=>address of this fun:0x8048a64
Point::func_zzy
the address of this --func_zzy:0x5
0x8048fc8
Point::callVtFuncs=>address of this fun:0x8048c8e
0x8048fcc
Point::callVtFuncs=>address of this fun:0x8048cda
0x8048fd0
Point::callVtFuncs=>address of this fun:0x8048cf8
Point::func_zzzy
the address of this --func_zzzy:0x11


func_hs:0x1
func_zzy:(nil)
func_zzzy:0x5
0x11
sizeof func:4
0x804880c
sizeof memfunc:8
0x8048bdc
0x11
sizeof virtmemfunc:8

data member那一塊比較簡單,沒有太大的問題。主要是virtual table這塊比較復(fù)雜 。第一個小問題就是
順序的問題。實驗證明在vtable中虛函數(shù)指針的順序是按照聲明時的順序放置的。不管virtual desctructor
在哪個位置,都會占據(jù)兩個slot,即有兩個virtual desctructor.至于為什么會有兩個,具體我也不是太清楚,
后面在討論。
我第一個有一個有疑問的地方就是關(guān)于typeinfo的問題。記得《Inside the c++ object model》中,Lippman
提到的對象模型中,將typeinfo放置在vtable的第一個slot中,而根據(jù)上面例子來看,第一個slot就是所聲明
的第一個virtual function.那么typeinfo存在何處?

vtable 的首地址是0x8048fc0,而從0x8048fb0開始的內(nèi)存地址信息如下:

(gdb) x/16a 0x8048fb0
0x8048fb0:      0x75253a63      0xa     0x0     0x8048fdc <_ZTI5Point>
0x8048fc0 <_ZTV5Point+8>:       0x8048a12 <Point::func_hs()>    0x8048a64 <Point::func_zzy()>   0x8048c8e <Point::~Point()>   0x8048cda <Point::~Point()>
0x8048fd0 <_ZTV5Point+24>:      0x8048cf8 <Point::func_zzzy()>  0x696f5035      0x746e  0x804a4c8 <_ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3+8>
0x8048fe0 <_ZTI5Point+4>:       0x8048fd4 <_ZTS5Point>  0x3b031b01      0x98    0x12

可以看出,在vtable之前也有關(guān)于Point類的信息,0x8048fbc處的值為
0x8048fdc <_ZTI5Point>,而0x8048fdc處的值為:0x804a4c8 <_ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3+8,可以猜測這是與類型有關(guān)的。


輸出中我在typeid(point)那一行設(shè)了斷點,進入函數(shù)之后可以看到:

(gdb) s
std::type_info::name (this=0x8048fdc)
    at /usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/typeinfo:102
102         { return __name[0] == '*' ? __name + 1 : __name; }
(gdb) n
5Point

point的類型信息為5Point,而type_info::name傳入的參數(shù)信息就是0x8048fdc.再看用
-fdump-class-hierarchy輸出的關(guān)于Point的類型信息:


Vtable for Point
Point::_ZTV5Point: 7u entries
0     (int (*)())0
4     (int (*)())(& _ZTI5Point)
8     (int (*)())Point::func_hs
12    (int (*)())Point::func_zzy
16    (int (*)())Point::~Point
20    (int (*)())Point::~Point
24    (int (*)())Point::func_zzzy

Class Point
   size=16 align=4
   base size=16 base align=4
Point (0xb60019a0) 0
    vptr=((& Point::_ZTV5Point) + 8u)


這樣的結(jié)果已經(jīng)相當(dāng)清楚。在g++的實現(xiàn)中,真正的typeinfo信息放置在vtable之后,其位置是通過vtable之前的地址內(nèi)
所包含的信息所指定。在整個關(guān)于Point類的這些信息里,起始位置為&Point::_ZTV5Point,其值為0x0,之后是關(guān)于類型
信息,然后才是vtable的入口點。即 vptr=((& Point::_ZTV5Point) + 8u)。point類的this指針通過類型轉(zhuǎn)化后所解
引用得到的值即使vptr.至于size=16很好理解,1個vptr+3個float.


另一個詭異的信息就是point to member的輸出,單個輸出是,3個virtual function分別是0x1 0x5 0x11,而在
printVirtualFunAddress中所輸出的信息卻很詭異,分別是0x1,nil,0x5,這就是為什么要在main函數(shù)中加入測試
函數(shù)指針大小的原因,普通函數(shù)是4個字節(jié),而成員函數(shù)的確是8個字節(jié),不管是不是virtual function.所以在printf
參數(shù)入棧的時候,要push兩次,將第二次push的結(jié)果當(dāng)作了第二個參數(shù)的值,以此后推。所以會有上面的結(jié)果。

最后就是那兩個desctructor的問題,在上面通過函數(shù)指針調(diào)用函數(shù)的時候要將他們都略過去。如果將virtual去掉,
那么vtable中就沒有desctructor。
下面是objdump出來的結(jié)果:objdump -d a.out|grep PointD

 8048932:    e8 51 03 00 00           call   8048c88 <_ZN5PointD1Ev>
 8048944:    e8 3f 03 00 00           call   8048c88 <_ZN5PointD1Ev>
08048c88 <_ZN5PointD1Ev>:
 8048cc5:    74 0b                    je     8048cd2 <_ZN5PointD1Ev+0x4a>
08048cd4 <_ZN5PointD0Ev>:
 8048ce0:    e8 a3 ff ff ff           call   8048c88 <_ZN5PointD1Ev>


兩個函數(shù)中,main調(diào)用的是<_ZN5PointD1Ev>,這就是我們上面聲明的那個virtual desctrucotr.而且在內(nèi)存布局中,
<_ZN5PointD1Ev>的位置比較靠前,其在vtable中的位置也應(yīng)在<_ZN5PointD0Ev>之前,而<_ZN5PointD0Ev>

08048cd4 <_ZN5PointD0Ev>:
 8048cd4:    55                       push   %ebp
 8048cd5:    89 e5                    mov    %esp,%ebp
 8048cd7:    83 ec 18                 sub    $0x18,%esp
 8048cda:    8b 45 08                 mov    0x8(%ebp),%eax
 8048cdd:    89 04 24                 mov    %eax,(%esp)
 8048ce0:    e8 a3 ff ff ff           call   8048c88 <_ZN5PointD1Ev>
 8048ce5:    8b 45 08                 mov    0x8(%ebp),%eax
 8048ce8:    89 04 24                 mov    %eax,(%esp)
 8048ceb:    e8 80 f9 ff ff           call   8048670 <_ZdlPv@plt>
 8048cf0:    c9                       leave  

的工作好像也要調(diào)用<_ZN5PointD1Ev>,這個應(yīng)該是編譯器生成的,再往深處我也不甚清楚了。



posted on 2012-08-10 11:17 西城 閱讀(2387) 評論(2)  編輯 收藏 引用 所屬分類: C/C++

Feedback

# re: 關(guān)于C++ 虛函數(shù)表的一些問題(g++) 2012-08-29 19:20 izualzhy
static void print()
{
//相對地址,在虛表指針之后.0x4 0x8 0xc --------->point to member
printf("&Point::x=%p\n&Point::y=%p\n&Point::z=%p\n",
&Point::x,&Point::y,&Point::z);
}

靜態(tài)函數(shù)使用非靜態(tài)成員,為什么可以編譯通過啊?  回復(fù)  更多評論
  

# re: 關(guān)于C++ 虛函數(shù)表的一些問題(g++) 2012-08-30 19:16 西城
@izualzhy
我又看了一下,確實是可以的。感覺&Point::x這種東西是與具體對象無關(guān)的,每個對象都一樣,所以我覺得從行為上來說應(yīng)該是與靜態(tài)成員一樣。  回復(fù)  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品久久午夜| 欧美性色视频在线| 欧美高清视频一二三区| 国产日韩免费| 亚洲欧美视频在线观看| 日韩视频亚洲视频| 欧美精品一卡| 9人人澡人人爽人人精品| 亚洲国产精品va| 久久久之久亚州精品露出| 国产一区免费视频| 久久露脸国产精品| 久久久久久高潮国产精品视| 一区二区在线观看av| 快she精品国产999| 久久婷婷国产综合国色天香| 伊甸园精品99久久久久久| 久久久99精品免费观看不卡| 欧美一区综合| 在线精品视频在线观看高清| 欧美大片免费| 欧美激情视频网站| 亚洲一区观看| 欧美一级视频免费在线观看| 狠狠狠色丁香婷婷综合激情| 久久夜色精品国产欧美乱| 久久久久久久欧美精品| 91久久在线播放| 亚洲精品一区中文| 国产精品系列在线| 麻豆成人在线| 欧美日韩国产首页在线观看| 午夜精品久久久99热福利| 亚洲一二三区在线| 狠狠综合久久av一区二区小说| 欧美国产精品| 欧美日韩在线视频首页| 久久成人精品一区二区三区| 久久久久久97三级| 99视频在线精品国自产拍免费观看| 99国产精品久久久久久久| 国产精品福利久久久| 久久久亚洲一区| 欧美精品乱人伦久久久久久| 亚洲欧美日韩视频一区| 久久久久久综合| 亚洲性视频网址| 久久免费的精品国产v∧| 日韩一区二区免费看| 亚洲综合视频在线| 先锋影音国产精品| 欧美另类一区| 牛牛精品成人免费视频| 一区二区冒白浆视频| 亚洲一区二区三区四区五区黄| 国产区亚洲区欧美区| 欧美福利视频在线| 国产精品日本精品| 亚洲第一色在线| 国产欧美日韩一区| 亚洲美女黄色| 在线观看国产精品网站| 亚洲少妇诱惑| 亚洲欧洲偷拍精品| 亚洲欧美日韩精品久久亚洲区| 亚洲国产一区在线| 欧美一级成年大片在线观看| 日韩视频―中文字幕| 羞羞答答国产精品www一本| 日韩视频在线一区| 久久伊伊香蕉| 久久九九全国免费精品观看| 欧美日韩精品免费看| 欧美调教vk| 欧美激情一区二区三区| 国产精品一区二区女厕厕| 亚洲国产欧美国产综合一区| 国产一区二区无遮挡| 亚洲天堂偷拍| 亚洲中午字幕| 欧美ed2k| 欧美高清视频一区二区| 激情综合在线| 欧美亚洲一级| 欧美在线视频不卡| 国产欧美日韩一级| 亚洲欧美中日韩| 先锋影音国产一区| 国产精品网站在线观看| 亚洲视频在线播放| 亚洲一区视频在线观看视频| 欧美日韩理论| 99热这里只有精品8| 亚洲一区二区免费视频| 欧美日韩精品一区二区| 亚洲最新视频在线播放| 亚洲一区二区三区精品动漫| 欧美系列精品| 亚洲午夜高清视频| 欧美一区国产一区| 国产亚洲aⅴaaaaaa毛片| 欧美伊人久久| 欧美成人精品在线播放| 在线观看日韩专区| 蜜桃av一区二区三区| 欧美激情影院| 国产精品99久久久久久久vr | 久久综合中文字幕| 欧美成人日韩| 亚洲美女在线观看| 欧美视频二区| 欧美一区二区三区视频| 浪潮色综合久久天堂| 亚洲成人在线网站| 欧美福利电影网| 一片黄亚洲嫩模| 亚洲一区二区欧美日韩| 校园激情久久| 激情综合自拍| 欧美精品一区二区三区四区| 一本色道久久综合亚洲精品高清| 亚洲欧美国产日韩中文字幕| 国产精品美女视频网站| 欧美在线亚洲| 亚洲日本欧美| 久久久五月天| 亚洲网址在线| 激情文学综合丁香| 欧美日韩精品高清| 欧美一区二区视频网站| 亚洲电影下载| 欧美一区二区三区免费观看| 在线高清一区| 国产精品视频网站| 欧美成人亚洲成人| 香港成人在线视频| 亚洲精品网站在线播放gif| 欧美与欧洲交xxxx免费观看| 亚洲高清不卡av| 国产精品看片你懂得| 欧美+亚洲+精品+三区| 亚洲欧美综合精品久久成人| 亚洲欧洲日本一区二区三区| 久久精品国产99精品国产亚洲性色| 亚洲欧洲综合| 狠狠色丁香婷婷综合影院| 欧美三级视频在线播放| 久久综合影音| 欧美与欧洲交xxxx免费观看| 日韩小视频在线观看| 欧美成人影音| 久久青草福利网站| 欧美亚洲综合另类| 这里只有精品视频| 亚洲人成在线观看| 极品av少妇一区二区| 国产拍揄自揄精品视频麻豆| 欧美日本一道本在线视频| 两个人的视频www国产精品| 香蕉久久久久久久av网站| 中文有码久久| 99riav1国产精品视频| 欧美激情一区二区三区 | 91久久中文字幕| 你懂的国产精品| 久久久国产精品一区二区中文| 亚洲一区二区精品在线| aaa亚洲精品一二三区| 亚洲国产欧美一区二区三区久久| 国产伊人精品| 国产一区久久久| 国内精品久久久久久久果冻传媒| 国产精品免费在线| 国产精品免费区二区三区观看| 欧美日韩亚洲一区二| 欧美日本一区二区三区| 欧美日本免费一区二区三区| 欧美剧在线观看| 欧美极品在线视频| 欧美另类亚洲| 国产精品久久久久久福利一牛影视| 欧美日韩喷水| 欧美四级伦理在线| 国产精品入口尤物| 国产女主播一区二区| 国产欧美婷婷中文| 国语自产精品视频在线看一大j8| 国产真实精品久久二三区| 国外成人在线视频| 亚洲国产二区| 亚洲欧美日韩国产中文在线| 亚洲在线网站| 午夜精品久久久久久久99樱桃| 亚洲欧美成人一区二区三区| 亚洲综合导航| 久久婷婷蜜乳一本欲蜜臀| 毛片av中文字幕一区二区| 欧美韩日一区| 国产精品免费观看视频| 狠狠色丁香婷婷综合|