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

Welcome to ErranLi's Blog!

  C++博客 :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
  106 Posts :: 1 Stories :: 97 Comments :: 0 Trackbacks

常用鏈接

留言簿(12)

搜索

  •  

積分與排名

  • 積分 - 178126
  • 排名 - 152

最新評(píng)論

閱讀排行榜


引用:http://m.shnenglu.com/stdyh/archive/2007/01/08/17442.html

C++對(duì)象內(nèi)存布局


寫(xiě)這個(gè)文章完全是因?yàn)橄胍闱宄?vc 怎么布局每個(gè) c++ 對(duì)象,以及怎樣完成指針的轉(zhuǎn)換的過(guò)程.
  先問(wèn)一個(gè)問(wèn)題,兩個(gè)不同類型的指針相互轉(zhuǎn)換以后,他們?cè)跀?shù)值上是一樣的嗎?比如:

    int nValue = 10;
    int *pInt = &nValue;
    void *pVoid = pInt;
    char *pChar = (char*)pInt;


   這些指針的值(不是說(shuō)指針指向的內(nèi)存的內(nèi)容)是一樣的嗎? 如果你的回答是 yes,那如果是一個(gè)類的繼承體系呢?在繼承類向基類轉(zhuǎn)換的過(guò)程中,指針的數(shù)值還是不變化的么?如果你的回答是"不一定會(huì)變化,要看類的體系是怎么設(shè)計(jì)的 "的話,那恭喜你,不用看下去了.如果你還不確定究竟變還是不變,究竟哪些變,哪些不變,究竟為什么要變?yōu)槭裁床蛔兊脑?接著看下來(lái).

   c++ 標(biāo)準(zhǔn)不規(guī)定 c++ 實(shí)現(xiàn)的時(shí)候的對(duì)象的具體的內(nèi)存布局,除了在某些方面有小的限制以外,c++ 對(duì)象在內(nèi)存里面的布局完全是由編譯器自行決定,這里我也只是討論 vc++ .net 2003 build 7.1.3091 的實(shí)現(xiàn)方式,我并沒(méi)有在 vc5 vc6 vc.net 2002 以及其他的 2003 build 上面做過(guò)測(cè)試,結(jié)論也許不適合那些編譯平臺(tái).這些屬于編譯器具體實(shí)現(xiàn),ms 保留有在不通知你我的情況下作出更改的權(quán)利.廢話這么多,馬上開(kāi)始.

  對(duì)于 c 的內(nèi)建指針的轉(zhuǎn)換,結(jié)果是不用多討論的,我們只是討論 c++ 的對(duì)象.從最簡(jiǎn)單的開(kāi)始.

    class CBase
    {
    public:
      int m_nBaseValue;
    };


  這樣的一個(gè)類在內(nèi)存里放置是非常簡(jiǎn)單的,他占有4個(gè) bytes 的空間,不用多說(shuō),我們從他派生一個(gè)類出來(lái).

    class CDerive1 : public CBase
    {
    public:
      int m_nDerive1Value;
    };


   CDerive1 的對(duì)象在內(nèi)存里面是怎么放的呢? 也很簡(jiǎn)單,占有8個(gè) bytes 的空間,前4個(gè) bytes 屬于 CBase 類,后四個(gè) bytes 屬于自己.一個(gè)CDerive1 的指針轉(zhuǎn)換成一個(gè) CBase 的指針,結(jié)果是一樣的.下面我們加上多重繼承看看.

    class CFinal : public CDerive,public CBase // 這里的 CDerive 是一個(gè)和 CBase 差不多的基類
    {
    public:
      int m_nFinalValue;
    };


   CFinal 的對(duì)象在內(nèi)存里面的布局稍微復(fù)雜一點(diǎn),但是也很容易想象,他占有 12 個(gè) bytes 的空間,前4個(gè)屬于 CDerive,中間4個(gè)屬于 CBase,后面4個(gè)才是自己的.那一個(gè) CFinal 的指針轉(zhuǎn)換成一個(gè) CDerive 指針,數(shù)值會(huì)變么? 轉(zhuǎn)換成一個(gè) CBase 指針呢?又會(huì)變化么?答案是,前一個(gè)不變,后一個(gè)要變化,道理非常的明顯,CFinal 對(duì)象的開(kāi)頭剛好是一個(gè) CDerive 對(duì)象,而 CBase 對(duì)象卻在 CFinal 對(duì)象的中間,自然是要變化的了,具體怎么變化呢? 加 4 就 ok(自然要檢查是否是空指針).

    CBase *pBase = pFinal ? (CBase*)((char*)pFinal + sizeof(CDerive)) : 0;// 當(dāng)你寫(xiě)下 pBase = pFinal 的時(shí)候,其實(shí)是這樣的

  這種不帶 virtual 的繼承就這么簡(jiǎn)單,只是加上一個(gè) offset 而已.下面我們看看如果加上 virtual function 的時(shí)候是什么樣子的呢?
還是從簡(jiǎn)單類開(kāi)始.

    class CBase
    {
    public:
      virtual void VirtualBaseFunction(){}
      int m_nBaseValue;
    };


   這里刻意沒(méi)有使用 virtual destructor,因?yàn)檫@個(gè)函數(shù)稍微有些不同.還是同樣的問(wèn)題,CBase 類在內(nèi)存上占多大的空間?還是 4 bytes 么? 答案是 no, 在我的編譯器上面是 8 bytes,多出來(lái)的 4 bytes 是 __vfptr(watch 窗口看見(jiàn)的名字),他是一個(gè)指針,指向了類的 vtable,那什么是 vtable 呢,他是用來(lái)干什么的呢? vtable 是用來(lái)支援 virtual function 機(jī)制的,他其實(shí)是一個(gè)函數(shù)指針數(shù)組(并不等同于c/c++語(yǔ)言里面的指針數(shù)組,因?yàn)樗麄兊念愋筒⒉灰欢ㄊ且粯拥?)他的每一個(gè)元素都指向了一個(gè)你定義的 virtual function,這樣通過(guò)一個(gè)中間層來(lái)到達(dá)動(dòng)態(tài)連編的效果,這些指針是在程序運(yùn)行的時(shí)候準(zhǔn)備妥當(dāng)?shù)?而不是在編譯的時(shí)候準(zhǔn)備妥當(dāng)?shù)?這個(gè)就是動(dòng)態(tài)聯(lián)編的 目的,具體是由誰(shuí)來(lái)設(shè)置這些指針的呢?constructor/destructor/copy constructor/assignment operator他們完成的,不用奇怪,編譯器會(huì)在你寫(xiě)的這些函數(shù)里面安插些必要的代碼用來(lái)設(shè)置 vtable 的值,如果你沒(méi)有寫(xiě)這些函數(shù),編譯器會(huì)在適當(dāng)?shù)臅r(shí)候幫你生成這些函數(shù).明白一點(diǎn), vtable 是用來(lái)支持 virtual function 機(jī)制的,而需要 virtual 機(jī)制的類基本上都會(huì)由一個(gè) __vfptr 指向他自己的 vtable.在調(diào)用 virtual function的時(shí)候,編譯器這樣完成:

   pBase->VirtualBaseFunction(); => pBase->__vfptr[0]();// 0 是你的virtual function 在 vtable 中的 slot number,編譯器決定

   現(xiàn)在應(yīng)該很想象 CBase 的大小了吧,那這個(gè) __vfptr 是放到什么位置的呢? 在 m_nBaseValue 之前還是之后呢? 在我的編譯器上看來(lái),是在之前,為什么要放到之前,是因?yàn)樵谕ㄟ^(guò) 指向類成員函數(shù)的指針調(diào)用 virtual function 的時(shí)候能少些代碼(指匯編代碼),這個(gè)原因這里就不深入討論了,有興趣的同學(xué)可以看看 inside the c++ object model 一書(shū).
  接下來(lái),我們加上繼承來(lái)看看.

    class CDerive1 : public CBase
    {
    public:
      virtual void VirtualDerive1Function();
    };


   這個(gè)時(shí)候你也許要說(shuō),內(nèi)存布局跟沒(méi)有 virtual 是一樣的,只不過(guò)每個(gè)類多了一個(gè) __vfptr 而已,呃...這個(gè)是不對(duì)的,在我的編譯器上面 兩個(gè)類共享同一個(gè) __vfptr, vtable 里面放有兩個(gè)指針,一個(gè)是兩個(gè)類共享的,一個(gè)只屬于 CDerive1 類,調(diào)用的時(shí)候如何呢?

   pDerive1->VirtualDerive1Function() => pDerive1->__vfptr[1]();
   pDerive1->VirtualBaseFunction() => pDerive1->__vfptr[0]();


  至于指針的相互轉(zhuǎn)換,數(shù)值還是沒(méi)有變化的(也正是追求這種效果,所以把 __vfptr 放到類的開(kāi)頭,因?yàn)檎{(diào)整 this 指針也是要占有運(yùn)行時(shí)的時(shí)間的).

   現(xiàn)在加上多重繼承瞧瞧,代碼我不寫(xiě)上來(lái)了,就跟上面的 CFinal, CDerive, CBase 體系一樣,只是每個(gè)類多一個(gè)VirtualxxxFunction出來(lái),這個(gè)時(shí)候的指針調(diào)整還是沒(méi)有什么變化,所以我們只是看看 vtable 的情況,你會(huì)說(shuō) CDerive 和 CFinal 共享一個(gè) __vfptr,而 CBase 有一個(gè)自己的 __vfptr,而 CFinal 的 __vfptr 有 2 個(gè)slot,這個(gè)結(jié)論是正確的. 同時(shí)你也會(huì)說(shuō) 通過(guò) CFinal 類調(diào)用 CBase 的函數(shù)是要進(jìn)行指針調(diào)整的,yes you'r right,不僅僅是 this 指針調(diào)整(呃,this 指針會(huì)成為 function 的一個(gè)參數(shù)),還要調(diào)整 vtable 的值:

   pFinal->VirtualBaseFunction() => (CBase*)((char*)pFinal + sizeof(CDerive))->__vfptr[0]();

   轉(zhuǎn)換成 asm 的代碼大約是這樣的:

   mov eax,[pFinal] ; pFinal is a local object,pFinal will be epb - xx
   add eax,8 ; 8 = sizeof(CDerive)
   mov ecx,eax ; ecx is this pointer
   mov edx,[eax] ; edx = vtable address
   call [edx] ; call vtable[0]


  寫(xiě)到這里也就明白this指針是怎么調(diào)整的.帶 virtual function 的繼承也不復(fù)雜,this指針調(diào)整也是很簡(jiǎn)單的,下面看最復(fù)雜的部分 virtual inheritance.

   我的編譯器支持虛擬繼承的方式和虛函數(shù)的方式差不多,都是通過(guò)一個(gè) table 完成,只是這個(gè)就看不到 vc 賦予的名字了,我們叫他 vbtable 吧,編譯器同樣在類里面加入一個(gè)指向 vbtable 的指針,我們叫他 __vbptr 吧,這個(gè)指針指向了 vbtable ,而 vbtable 里面的每一項(xiàng)對(duì)應(yīng)了一個(gè)基類,vbtable 記錄了每個(gè)基類的某一個(gè)偏移量,通過(guò)這個(gè)偏移量就能計(jì)算出具體類的指針的位置.看個(gè)簡(jiǎn)單的例子:

   class CBase
   {
   public:
     virtual ~CBase(){}
   };

   class CMid1 : public virtual CBase
   {
   public:
     virtual ~CMid1(){}
     int m_nMid1;
   };

   class CMid2 : public virtual CBase
   {
   public:
     virtual ~CMid2(){}
     int m_nMid2;
   };

   class CFinal : public CMid1,public CMid2
   {
   public:
     virtual ~CFinal(){}
     int m_nFinal;
   };

   CFinal final;
   CFinal *pFinal = &final;??? // pFinal = 0x0012feb4;
   CBase *pBase = pFinal; // pBase = 0x0012fec8 = pFinal + 0x14;
   CMid1 *pMid1 = pFinal; // pMid1 = 0x0012feb4 = pFinal;
   CMid2 *pMid2 = pFinal; // pMid2 = 0x004210b4 = pFinal;


   結(jié)果讓你吃驚嗎? 最奇怪的地方居然是 CMid2 和 CMid1 的地址居然是一樣的,這個(gè)是因?yàn)?vc 把 vbtable 放到了 CFinal 類的開(kāi)頭的原因,而CMid1 和 CMid2 也同樣要使用這個(gè) vbtable, 所以 這個(gè)三個(gè)的地址也就必須相同了.那 CBase 的地址是怎么出來(lái)的呢? 呃...剛剛我們說(shuō)了 vbtable 放到了CFinal 的開(kāi)頭(vc 一定會(huì)放在開(kāi)頭嗎?答案是不一定,這個(gè)稍后解釋).在我的機(jī)器上面 final 對(duì)應(yīng)內(nèi)存的第一個(gè) dword 是 0x00426030,查看這個(gè)地址,第一個(gè)dword 是 0 ,第二個(gè)就是 0x14,剛好和 pBase 的偏移相同,這個(gè)只是巧合,也許你換個(gè)類的繼承體系就完全不同了,但是我只是想說(shuō)明一點(diǎn),基類的偏移計(jì)算是和 vbtable 的值相關(guān)聯(lián)的.下面我們就來(lái)看看 vc 是怎么計(jì)算這些偏移的.
  vc 在分析我們的代碼的時(shí)候,生成了一份類的繼承體系信息,其中有一個(gè)叫 thisDisplacement 的_PMD結(jié)構(gòu):

    struct _PMD // total undocumented
    {
      int mdisp; // i think the meaning is Multiinheritance DISPlacement
      int pdisp; // Pointer to vbtable DISPlacement
      int vdisp; // Vbtable DISPlacement
    };


   結(jié)構(gòu)的名字和成員變量的名字確確實(shí)實(shí)是 vc 的名字(在 watch 窗口輸入 (_PMD*)0 就能看到這個(gè)結(jié)構(gòu)的詳細(xì)信息),每個(gè)字段的含義卻是我自己猜測(cè)出來(lái)的.mdisp 大概用來(lái)表示多重繼承(包括單一繼承)的時(shí)候的偏移量,pdisp 表示 vbtable 的偏移量,而 vdisp 表示類在 vbtable 里面的下標(biāo).那么有了這個(gè)結(jié)構(gòu)怎樣才能完成指針的轉(zhuǎn)換呢?假如我們有一個(gè)派生類指針 pFinal,要轉(zhuǎn)換成一個(gè)特定的基礎(chǔ)類,我們首先要知道和這個(gè)基類對(duì)應(yīng)的 _PMD 結(jié)構(gòu)的信息(這個(gè)信息的獲取,我暫時(shí)沒(méi)有找到一個(gè)非常方便的方法,現(xiàn)在我使用的方法下面會(huì)有描述),有了這個(gè)信息以后,轉(zhuǎn)換就方便了.首先找到 vbtabel 的地址 *(pFinal + pdisp),然后找到基類的偏移 *(*(pFinal + pdisp) + vdisp) 這個(gè)偏移值是相對(duì)vbtable的,所以還要加上 vbtable的偏移,最后加上 mdisp的偏移,如下:

  char *pFinal = xxx; // need a init value
  char *pBase; // we must calc
  pBase = pFinal + mdisp + *(int *)(*(int *)(pFinal + pdisp) + vdisp) + pdisp;


  注意: 當(dāng) pdisp < 0 的時(shí)候就表示這個(gè)類沒(méi)有 vbtable 直接使用 pFinal + mdisp 就得到結(jié)果了.
  所以這個(gè)結(jié)構(gòu)是一個(gè)通用的結(jié)構(gòu),專門用作類型轉(zhuǎn)換,不管是有無(wú)虛繼承都能使用這個(gè)結(jié)構(gòu)進(jìn)行類型轉(zhuǎn)換.

  通過(guò)這個(gè)結(jié)構(gòu),我們也能看到 vc 是怎樣布局這個(gè) object 的.

  看到這里,也許你要大呼一口氣,媽媽呀,一個(gè)類型轉(zhuǎn)換要這么的麻煩嗎?我直接寫(xiě) pBase = pFinal 不就可以了嗎? 恭喜你還沒(méi)有被我忽悠得暈頭轉(zhuǎn)向,哈哈.其實(shí)你寫(xiě)下那行語(yǔ)句的時(shí)候,編譯器在幫你做這個(gè)轉(zhuǎn)換,大約生成下面的代碼

    mov eax,[pFinal] ;final address
    mov ecx,[eax] ; vbtable address *(int *)(pFinal + pdisp)
    mov edx,eax ; save to edx
    add edx,[ecx + 4] ; ecx + 4 is (*(int *)(pFinal + pdisp) + vdisp)
    mov [pBase],edx ; edx = pFinal + mdisp + *(int *)(*(int *)(pFinal + pdisp) + vdisp) + pdisp;
    ; here mdisp = 0, pdisp = 0, vdisp = 4


   也許你要說(shuō)了,我要這些東西來(lái)干什么?要轉(zhuǎn)換的時(shí)候直接轉(zhuǎn)換就好了,編譯器會(huì)幫做,的確,大多數(shù)的時(shí)候確實(shí)是這樣,但是,在某些時(shí)候卻并不如此,現(xiàn)在你 要實(shí)現(xiàn)一個(gè)功能,輸入一個(gè)指針,輸入一個(gè) _PMD 結(jié)構(gòu),你要實(shí)現(xiàn)一個(gè)AdjustPointer 的函數(shù)來(lái)生成另一個(gè)指針.這個(gè)時(shí)候你也只能這樣完成了,因?yàn)槲覜](méi)有給你兩個(gè)指針的名字,就算給了你字符串形式的名字也沒(méi)有用,呃....你也許會(huì)說(shuō),辦法 是有的,的確是有,模板就能實(shí)現(xiàn)這種功能,呵..這個(gè)我們暫時(shí)不討論具體的實(shí)現(xiàn)細(xì)節(jié).也許你要問(wèn)了,究竟什么時(shí)候會(huì)去實(shí)現(xiàn)這種聽(tīng)都沒(méi)有聽(tīng)過(guò)的功能,其實(shí)這 個(gè)函數(shù)是真正存在的,只不過(guò)不是由你來(lái)實(shí)現(xiàn)的,而是 ms 的人實(shí)現(xiàn)的,你只用寫(xiě)一個(gè) 帶有 c++ 異常的程序,使用 ida 反匯編,然后查找函數(shù),就能找到這個(gè)函數(shù)了,他用來(lái)在異常處理時(shí)創(chuàng)建 catch 所需要的 object.至于這個(gè)詳細(xì)的信息,請(qǐng)期待.我會(huì)最快速度寫(xiě)出關(guān)于 vc 是怎樣實(shí)現(xiàn) c++ 異常的文章來(lái).

  最后了,說(shuō)說(shuō)那個(gè) _PMD 結(jié)構(gòu)的獲取方式.看的時(shí)候不要吃驚,方法比較的麻煩,比如我想知道和 CFinal 類相關(guān)的 _PMD 信息,先新建工作,寫(xiě)下 throw pFinal 這樣的語(yǔ)句,編譯,在這個(gè)語(yǔ)句的地方設(shè)置斷點(diǎn),運(yùn)行,轉(zhuǎn)到反匯編,進(jìn)入 __CxxThrowException@8 函數(shù),這個(gè)時(shí)候不出意外你能看到一個(gè)叫 pThrowInfo 的東西(如果看不到,請(qǐng)打開(kāi)"顯示符號(hào)名"選項(xiàng)),在 watch 窗口里面輸入pThrowInfo,展開(kāi)他,看到一個(gè)pCatchableTypeArray,記錄下他的 nCacthableTypes的值,然后在 watch 里面輸入
pThrowInfo->pCatchableTypeArray->arrayOfCatchableTypes[0] 到 pThrowInfo->pCatchableTypeArray->arrayOfCatchableTypes[n], n 就是你剛剛記錄的值減1,再展開(kāi)他們,你就能看到一個(gè) thisDisplacement 的數(shù)據(jù),繼續(xù)展開(kāi)就是 mdisp 等等了,很是麻煩吧.哈..你已經(jīng)猜到了,這個(gè)是和異常有關(guān)系的.

  后記: 這段時(shí)間,我一直在讀些反匯編之后的代碼,也頗有些心得,所以才有想法寫(xiě)一些文章,探討 vc 編譯器鮮為人知(太過(guò)狂妄了)的秘密,這個(gè)方面的文章也有人寫(xiě)過(guò),那些文章也給我不少的啟發(fā),我不認(rèn)為自己是第一個(gè)發(fā)現(xiàn)這些秘密的人,但是至少我自己知道 的,我是第一個(gè)把這些東西寫(xiě)出來(lái)的人.文章里面作墨多的部分都是自己發(fā)現(xiàn)的.就這個(gè)文章里面的內(nèi)容來(lái)說(shuō),inside the c++ object model 是有比較詳細(xì)的描寫(xiě),但是他并不是轉(zhuǎn)換針對(duì) vc 這個(gè)編譯器的實(shí)現(xiàn),而 _PMD 這個(gè)結(jié)構(gòu)我也沒(méi)有在什么地方見(jiàn)有人描述過(guò),只是在 windows develop network 的2002年12月的雜志上看有人提到過(guò)這個(gè)結(jié)構(gòu),可惜他卻沒(méi)有了解(至少他在他發(fā)表文章的時(shí)候是如是說(shuō)的)這個(gè)結(jié)構(gòu)的用處(正是因?yàn)檫@個(gè)原因,我才有寫(xiě) 這個(gè)文章以及后續(xù)文章的沖動(dòng)).所以,這個(gè)文章也算是我自己的原創(chuàng)吧.這個(gè)文件雖然和游戲制造沒(méi)有太大的關(guān)系,但是小 T 自視清高,不愿意自己的文章被一幫不懂的人評(píng)價(jià)來(lái)評(píng)價(jià)去的,所以也沒(méi)有發(fā)到那些著名的 xxx 網(wǎng)站,只發(fā) goldpoint.轉(zhuǎn)載請(qǐng)注明出處(小 T 對(duì)自己的第一個(gè)原創(chuàng)文章比較珍惜,比較重視,謝謝).


posted on 2007-10-14 00:37 erran 閱讀(1528) 評(píng)論(1)  編輯 收藏 引用 所屬分類: C & C++

Feedback

# re: 轉(zhuǎn):C++對(duì)象內(nèi)存布局 2008-08-10 16:10 AlexEric
雖然不是第一次看到這方面的內(nèi)容,不過(guò)寫(xiě)得還是不錯(cuò)的。  回復(fù)  更多評(píng)論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美母乳在线| 精品电影在线观看| 国产精品精品视频| 亚洲国产精品日韩| 久久久久看片| 亚洲女爱视频在线| 欧美午夜精品理论片a级按摩| 狠狠久久亚洲欧美专区| 亚洲欧美日韩在线综合| 亚洲人成网站999久久久综合| 欧美一级网站| 国产一区在线免费观看| 久久精品一区蜜桃臀影院| 99精品久久| 亚洲国产日韩在线一区模特| 久久夜色撩人精品| 欧美一区二区在线免费观看| 国产精品丝袜91| 欧美一区二区三区视频在线| 午夜精品久久久久久99热软件 | 欧美大成色www永久网站婷| 雨宫琴音一区二区在线| 欧美jizz19性欧美| 欧美激情久久久久久| 日韩视频一区| 亚洲视频一二| 国产欧美日韩亚洲一区二区三区| 欧美专区在线播放| 久久亚洲视频| 99国产成+人+综合+亚洲欧美| 亚洲麻豆视频| 国产欧美日韩视频一区二区| 裸体女人亚洲精品一区| 欧美经典一区二区| 欧美巨乳在线观看| 午夜精品久久久久久久久久久久久| 亚洲欧美日韩专区| 91久久久久久| 亚洲一区自拍| 91久久久久久久久| 亚洲一区二区成人在线观看| 一色屋精品视频在线观看网站| 亚洲激情午夜| 国产一区二区三区在线免费观看| 欧美激情第三页| 国产精品一区二区三区观看 | 久久精品99| 亚洲美女视频在线观看| 亚洲性图久久| 最新69国产成人精品视频免费| 一区二区电影免费在线观看| 精品福利免费观看| 一区二区三区三区在线| 在线成人亚洲| 亚洲欧美精品伊人久久| 亚洲激情社区| 性欧美在线看片a免费观看| 日韩系列在线| 久久亚洲图片| 久久精品免费电影| 欧美色大人视频| 欧美激情第9页| 精品av久久久久电影| 亚洲午夜精品视频| 9国产精品视频| 裸体素人女欧美日韩| 久久精品在线| 国产精品进线69影院| 亚洲日本理论电影| 亚洲国产日韩一级| 久久久夜精品| 久久欧美中文字幕| 国产一级揄自揄精品视频| 中文国产成人精品久久一| 91久久综合| 久久人人精品| 欧美女激情福利| 久久久精品一区二区三区| 欧美日韩亚洲综合在线| 欧美大胆人体视频| 黄色亚洲网站| 欧美一区二区视频网站| 欧美一区二区成人| 国产精品久久久久久久一区探花| 亚洲风情在线资源站| 在线免费观看视频一区| 久久国产加勒比精品无码| 欧美专区第一页| 国产伪娘ts一区| 欧美怡红院视频一区二区三区| 午夜精品亚洲一区二区三区嫩草| 欧美午夜精品理论片a级按摩| 亚洲精一区二区三区| 欧美精品免费看| 欧美成人影音| 亚洲精选久久| 欧美日韩中文在线观看| 中日韩美女免费视频网址在线观看 | 国产日韩一区二区三区在线| 午夜精品福利视频| 久久高清国产| 影音先锋久久精品| 欧美成年人视频网站| 亚洲福利精品| 亚洲私人影院在线观看| 欧美日韩你懂的| 亚洲深夜影院| 久久精品三级| 亚洲激情网站| 欧美精品粉嫩高潮一区二区 | 亚洲特级毛片| 久久久久久国产精品mv| 欲色影视综合吧| 欧美精品导航| 亚洲免费一区二区| 欧美bbbxxxxx| 亚洲一区二区三区在线| 国产综合18久久久久久| 久热国产精品| 一区二区三区高清不卡| 久久激情网站| 亚洲三级电影全部在线观看高清| 欧美日韩国产成人在线91| 亚洲男人av电影| 亚洲大胆人体在线| 亚洲欧美成人网| 亚洲国产精品久久久久| 欧美日韩国产一区二区三区地区 | 亚洲校园激情| 免费视频一区二区三区在线观看| 欧美视频手机在线| 欧美一区三区二区在线观看| 亚洲国产精品va| 欧美一区二区三区精品| 亚洲国产影院| 国产视频在线观看一区二区三区| 免费91麻豆精品国产自产在线观看| 一区二区日韩伦理片| 男人插女人欧美| 欧美一区影院| 9l国产精品久久久久麻豆| 韩曰欧美视频免费观看| 欧美日韩一区三区| 久久一区中文字幕| 亚洲欧洲av一区二区三区久久| 黄色成人片子| 国产欧美韩国高清| 欧美色图麻豆| 欧美激情精品久久久久久| 久久精品在线观看| 亚洲素人在线| 亚洲精品一区二区在线| 欧美国产免费| 久久久蜜臀国产一区二区| 午夜国产精品视频| 一区二区欧美在线观看| 亚洲高清资源综合久久精品| 国产欧美日韩中文字幕在线| 欧美日韩裸体免费视频| 欧美xxx成人| 久久躁狠狠躁夜夜爽| 欧美在线一二三| 性感少妇一区| 亚洲欧美另类国产| 亚洲一区3d动漫同人无遮挡| 亚洲作爱视频| 在线视频你懂得一区| 日韩一级免费| 夜夜嗨一区二区三区| 99热这里只有精品8| 日韩视频不卡| 一区二区免费看| 夜夜爽99久久国产综合精品女不卡| 亚洲国产日日夜夜| 亚洲国产一区二区三区a毛片| 欧美激情精品久久久久久黑人| 欧美成人亚洲| 亚洲黄色大片| 亚洲免费观看| 一本色道88久久加勒比精品| 日韩一区二区久久| 亚洲视频在线看| 午夜精品剧场| 久久狠狠婷婷| 免播放器亚洲| 欧美日韩国产一级| 国产精品女人久久久久久| 国产精品视频成人| 国产一区二区中文| 在线成人激情| 亚洲精品欧美日韩专区| 一区二区三区三区在线| 亚洲欧美另类在线| 久久国产日本精品| 美脚丝袜一区二区三区在线观看 | 日韩视频一区二区三区在线播放免费观看 | 一区二区三区精品视频| 午夜视频在线观看一区二区| 久久av老司机精品网站导航| 鲁大师成人一区二区三区|