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

隨筆 - 42  文章 - 3  trackbacks - 0
<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用鏈接

留言簿(2)

隨筆檔案

文章檔案

網頁收藏

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

白楊

http://baiy.cn

 

 

在我?guī)啄昵伴_始寫《C++編碼規(guī)范與指導》一文時,就已經規(guī)劃著要加入這樣一篇討論 C++ 異常機制的文章了。沒想到時隔幾年以后才有機會把這個尾巴補完 :-)。

還是那句開場白:“在恰當的場合使用恰當的特性” 對每個稱職的 C++ 程序員來說都是一個基本標準。想要做到這點,就必須要了解語言中每個特性的實現方式及其時空開銷。異常處理由于涉及大量底層內容,向來是 C++ 各種高級機制中較難理解和透徹掌握的部分。本文將在盡量少引入底層細節(jié)的前提下,討論 C++ 中這一嶄新特性,并分析其實現開銷:

 

關于線程

進程和線程的概念相信各位看官早已耳熟能詳。在這里,我只想帶大家回憶幾點重要概念:
  1. 一個進程中可以同時包含多個線程。
     
  2. 我們通常認為線程是操作系統(tǒng)可識別的最小并發(fā)執(zhí)行和調度單位(不要跟俺說還有 Green Thread 或者 Fiber,OS Kernel 不認識也不參與這些物件的調度)。
     
  3. 同一進程中的多個線程共享代碼段(代碼和常量)、數據段(靜態(tài)和全局變量)和擴展段(堆存儲),但是每個線程有自己的棧段。棧段又叫運行時棧,用來存放所有局部變量和臨時變量(參數、返回值、臨時構造的變量等)。這一條對下文中的某些概念來說是非常重要的 。但是請注意,這里提到的各個“段”都是邏輯上的說法,在物理上某些硬件架構或者操作系統(tǒng)可能不使用段式存儲。不過沒關系,編譯器會保證這些邏輯概念和假設的前提條件對每個 C/C++ 程序員來說始終是成立的。
     
  4. 由于共享了除棧以外的所有內存地址段,線程不可以有自己的“靜態(tài)”或“全局”變量,為了彌補這一缺憾,操作系統(tǒng)通常會提供一種稱為 TLS(Thread Local Storage,即:“線程本地存儲”)的機制。通過該機制可以實現類似的功能。TLS 通常是線程控制塊(TCB)中的某個指針所指向的一個指針數組,數組中的每個元素稱為一個槽(Slot),每個槽中的指針由使用者定義,可以指向任意位置(但通常是指向堆存儲中的某個偏移)。

 

函數的調用和返回

接著我們來回顧下一個預備知識:編譯器如何實現函數的調用和返回。一般來說,編譯器會為當前調用棧里的每個函數建立一個??蚣埽⊿tack Frame)。“??蚣?#8221;擔負著以下重要任務:
  1. 傳遞參數:通常,函數的調用參數總是在這個函數??蚣艿淖铐敹恕?/li>
  2. 傳遞返回地址:告訴被調用者的 return 語句應該 return 到哪里去,通常指向該函數調用的下一條語句(代碼段中的偏移)。
  3. 存放調用者的當前棧指針:便于清理被調用者的所有局部變量、并恢復調用者的現場。
  4. 存放當前函數內的所有局部變量:記得嗎?剛才說過所有局部和臨時變量都是存儲在棧上的。

最后再復習一點:棧是一種“后進先出”(LIFO)的數據結構,不過實際上大部分棧的實現都支持隨機訪問。

下面我們來看個具體例子:

假設有 FuncA、FuncB 和 FuncC 三個函數,每個函數均接收兩個整形值作為其參數。在某線程上的某一時間段內,FuncA 調用了 FuncB,而 FuncB 又調用了 FuncC。則,它們的??蚣芸雌饋響撓襁@樣:


圖1 函數調用??蚣苁纠?/p>

正如上圖所示的那樣,隨著函數被逐級調用,編譯器會為每一個函數建立自己的棧框架,??臻g逐漸消耗。隨著函數的逐級返回,該函數的??蚣芤矊⒈恢鸺変N毀,??臻g得以逐步釋放。順便說一句,遞歸函數的嵌套調用深度通常也是取決于運行時??臻g的剩余尺寸。

這里順便解釋另一個術語:調用約定(calling convention)。調用約定通常指:調用者將參數壓入棧中(或放入寄存器中)的順序,以及返回時由誰(調用者還是被調用者)來清理這些參數等細節(jié)規(guī)程方面的約定。

最后再說一句,這里所展示的函數調用乃是最“經典”的方式。實際情況是:在開啟了優(yōu)化選項后,編譯器可能不會為一個內聯甚至非內聯的函數生成??蚣?,編譯器可能使用很多優(yōu)化技術消除這個構造。不過對于一個 C/C++ 程序員來說,達到這樣的理解程度通常就足夠了。


 

C++ 函數的調用和返回

首先澄清一點,這里說的 “C++ 函數”是指:
  1. 該函數可能會直接或間接地拋出一個異常:即該函數的定義存放在一個 C++ 編譯(而不是傳統(tǒng) C)單元內,并且該函數沒有使用“throw()”異常過濾器。
  2. 或者該函數的定義內使用了 try 塊。

以上兩者滿足其一即可。為了能夠成功地捕獲異常和正確地完成棧回退(stack unwind),編譯器必須要引入一些額外的數據結構和相應的處理機制。我們首先來看看引入了異常處理機制的??蚣艽蟾攀鞘裁礃幼樱?/p>


圖2 C++函數調用??蚣苁纠?/p>

由圖2可見,在每個 C++ 函數的??蚣苤卸级嗔艘恍〇|西。仔細觀察的話,你會發(fā)現,多出來的東西正好是一個 EXP 類型的結構體。進一步分析就會發(fā)現,這是一個典型的單向鏈表式結構:

  • piPrev 成員指向鏈表的上一個節(jié)點,它主要用于在函數調用棧中逐級向上尋找匹配的 catch 塊,并完成?;赝斯ぷ?。

  • piHandler 成員指向完成異常捕獲和棧回退所必須的數據結構(主要是兩張記載著關鍵數據的表:“try”塊表:tblTryBlocks 及“?;赝吮?#8221;:tblUnwind)。

  • nStep 成員用來定位 try 塊,以及在?;赝吮碇袑ふ艺_的入口。

需要說明的是:編譯器會為每一個“C++ 函數”定義一個 EHDL 結構,不過只會為包含了“try”塊的函數定義 tblTryBlocks 成員。此外,異常處理器還會為每個線程維護一個指向當前異常處理框架的指針。該指針指向異常處理器鏈表的鏈尾,通常存放在某個 TLS 槽或能起到類似作用的地方。

最后,請再看一遍圖2,并至少對其中的數據結構留下一個大體印象。我們會在后面多個小節(jié)中詳細討論它們。

注意:為了簡化起見,本文中描述的數據結構內,大多省略了一些與話題無關的成員。

 

?;赝耍⊿tack Unwind)機制

“棧回退”是伴隨異常處理機制引入 C++ 中的一個新概念,主要用來確保在異常被拋出、捕獲并處理后,所有生命期已結束的對象都會被正確地析構,它們所占用的空間會被正確地回收。

受益于棧回退機制的引入,以及 C++ 類所支持的“資源申請即初始化”語意,使得我們終于能夠徹底告別既不優(yōu)雅也不安全的 setjmp/longjmp 調用,簡便又安全地實現遠程跳轉了。我想這也是 C++ 異常處理機制在錯誤處理以外唯一一種合理的應用方式了。

下面我們就來具體看看編譯器是如何實現?;赝藱C制的:


圖3 C++ 棧回退機制

圖3中的“FuncUnWind”函數內,所有真實代碼均以黑色和藍色字體標示,編譯器生成的代碼則由灰色和橙色字體標明。此時,在圖2里給出的 nStep 變量和 tblUnwind 成員作用就十分明顯了。

nStep 變量用于跟蹤函數內局部對象的構造、析構階段。再配合編譯器為每個函數生成的 tblUnwind 表,就可以完成退棧機制。表中的 pfnDestroyer 字段記錄了對應階段應當執(zhí)行的析構操作(析構函數指針);pObj 字段則記錄了與之相對應的對象 this 指針偏移。將 pObj 所指的偏移值加上當前??蚣芑罚‥BP),就是要代入 pfnDestroyer 所指析構函數的 this 指針,這樣即可完成對該對象的析構工作。而 nNextIdx 字段則指向下一個需要析構對象所在的行(下標)。

在發(fā)生異常時,異常處理器首先檢查當前函數棧框架內的 nStep 值,并通過 piHandler 取得 tblUnwind[] 表。然后將 nStep 作為下標帶入表中,執(zhí)行該行定義的析構操作,然后轉向由 nNextIdx 指向的下一行,直到 nNextIdx 為 -1 為止。在當前函數的棧回退工作結束后,異常處理器可沿當前函數棧框架內 piPrev 的值回溯到異常處理鏈中的上一節(jié)點重復上述操作,直到所有回退工作完成為止。

值得一提的是,nStep 的值完全在編譯時決定,運行時僅需執(zhí)行若干次簡單的整形立即數賦值(通常是直接賦值給CPU里的某個寄存器)。此外,對于所有內部類型以及使用了默認構造、析構方法(并且它的所有成員和基類也使用了默認方法)的類型,其創(chuàng)建和銷毀均不影響 nStep 的值。

注意:如果在?;赝说倪^程中,由于析構函數的調用而再次引發(fā)了異常(異常中的異常),則被認為是一次異常處理機制的嚴重失敗。此時進程將被強行禁止。為防止出現這種情況,應在所有可能拋出異常的析構函數中使用“std::uncaught_exception()”方法判斷當前是否正在進行?;赝耍矗捍嬖谝粋€未捕獲或未完全處理完畢的異常)。如是,則應抑制異常的再次拋出。

 

異常捕獲機制

一個異常被拋出時,就會立即引發(fā) C++ 的異常捕獲機制:


圖4 C++ 異常捕獲機制

在上一小節(jié)中,我們已經看到了 nStep 變量在跟蹤對象構造、析構方面的作用。實際上 nStep 除了能夠跟蹤對象創(chuàng)建、銷毀階段以外,還能夠標識當前執(zhí)行點是否在 try 塊中,以及(如果當前函數有多個 try 塊的話)究竟在哪個 try 塊中。這是通過在每一個 try 塊的入口和出口各為 nStep 賦予一個唯一 ID 值,并確保 nStep 在對應 try 塊內的變化恰在此范圍之內來實現的。

在具體實現異常捕獲時,首先,C++ 異常處理器檢查發(fā)生異常的位置是否在當前函數的某個 try 塊之內。這項工作可以通過將當前函數的 nStep 值依次在 piHandler 指向 tblTryBlocks[] 表的條目中進行范圍為 [nBeginStep, nEndStep) 的比對來完成。

例如:若圖4 中的 FuncB 在 nStep == 2 時發(fā)生了異常,則通過比對 FuncB 的 tblTryBlocks[] 表發(fā)現 2∈[1, 3),故該異常發(fā)生在 FuncB 內的第一個 try 塊中。

其次,如果異常發(fā)生的位置在當前函數中的某個 try 塊內,則嘗試匹配該 tblTryBlocks[] 相應條目中的 tblCatchBlocks[] 表。tblCatchBlocks[] 表中記錄了與指定 try 塊配套出現的所有 catch 塊相關信息,包括這個 catch 塊所能捕獲的異常類型及其起始地址等信息。

若找到了一個匹配的 catch 塊,則復制當前異常對象到此 catch 塊,然后跳轉到其入口地址執(zhí)行塊內代碼。

否則,則說明異常發(fā)生位置不在當前函數的 try 塊內,或者這個 try 塊中沒有與當前異常相匹配的 catch 塊,此時則沿著函數??蚣苤?piPrev 所指地址(即:異常處理鏈中的上一個節(jié)點)逐級重復以上過程,直至找到一個匹配的 catch 塊或到達異常處理鏈的首節(jié)點。對于后者,我們稱為發(fā)生了未捕獲的異常,對于 C++ 異常處理器而言,未捕獲的異常是一個嚴重錯誤,將導致當前進程被強制結束。

注意:雖然在圖4示例中的 tblTryBlocks[] 只有一個條目,這個條目中的 tblCatchBlocks[] 也只有一行。但是在實際情況中,這兩個表中都允許有多條記錄。意即:一個函數中可以有多個 try 塊,每個 try 塊后均可跟隨多個與之配套的 catch 塊。

注意:按照標準意義上的理解,異常時的棧回退是伴隨著異常捕獲過程沿著異常處理鏈逐層向上進行的。但是有些編譯器是在先完成異常捕獲后再一次性進行?;赝说?。無論具體實現使用了哪種方式,除非正在開發(fā)一個內存嚴格受限的嵌入式應用,通常我們按照標準語意來理解都不會產生什么問題。

備注:實際上 tblCatchBlocks 中還有一些較為關鍵但被故意省略的字段。比如指明該 catch 塊異常對象復制方式(傳值(拷貝構造)或傳址(引用或指針))的字段,以及在何處存放被復制的異常對象(相對于入口地址的偏移位置)等信息。

 
 

異常的拋出

接下來討論整個 C++ 異常處理機制中的最后一個環(huán)節(jié),異常的拋出:


圖5 C++ 異常拋出

在編譯一段 C++ 代碼時,編譯器會將所有 throw 語句替換為其 C++ 運行時庫中的某一指定函數,這里我們叫它 __CxxRTThrowExp(與本文提到的所有其它數據結構和屬性名一樣,在實際應用中它可以是任意名稱)。該函數接收一個編譯器認可的內部結構(我們叫它 EXCEPTION 結構)。這個結構中包含了待拋出異常對象的起始地址、用于銷毀它的析構函數,以及它的 type_info 信息。對于沒有啟用 RTTI 機制(編譯器禁用了 RTTI 機制或沒有在類層次結構中使用虛表)的異常類層次結構,可能還要包含其所有基類的 type_info 信息,以便與相應的 catch 塊進行匹配。

在圖5中的深灰色框圖內,我們使用 C++ 偽代碼展示了函數 FuncA 中的 “throw myExp(1);” 語句將被編譯器最終翻譯成的樣子。實際上在多數情況下,__CxxRTThrowExp 函數即我們前面曾多次提到的“異常處理器”,異常捕獲和?;赝说雀黜椫匾ぷ鞫加伤鼇硗瓿?。

__CxxRTThrowExp 首先接收(并保存)EXCEPTION 對象;然后從 TLS:Current ExpHdl 處找到與當前函數對應的 piHandler、nStep 等異常處理相關數據;并按照前文所述的機制完成異常捕獲和棧回退。由此完成了包括“拋出”->“捕獲”->“回退”等步驟的整套異常處理機制。

 

Windows 中的結構化異常處理

Microsoft Windows 帶有一種名為“結構化異常處理”的機制,非常著名的“內存訪問違例”出錯對話框就是該機制的一種體現。Windows 結構化異常處理與前文討論的 C++ 異常處理機制有驚人的相似之處,同樣使用類似的鏈式結構實現。對于 Windows 下的應用程序,只需使用 SetUnhandledExceptionFilter API 注冊異常處理器;用 FS:[0] 替代前文所述的 TLS: Current ExpHdl 等很少的改動,即可將此兩種錯誤處理機制合而為一。這樣做的優(yōu)勢十分明顯:
  • 由于可直接借助操作系統(tǒng)提供的機制,所以簡化了 C++ 異常處理器的實現。
  • 使“catch (...)” 塊得以捕獲操作系統(tǒng)產生的異常(如:“內存訪問違例”等等)。
  • 使操作系統(tǒng)的異常處理機制能夠捕獲所有 C++ 異常。

實際上,大多數 Windows 下的 C++ 編譯器的異常機制均使用這種方式實現。

 
 

異常處理機制的開銷分析

至此,我們已完整地闡述了整套 C++ 異常處理機制的實現原理。我在本文的開頭曾提到,作為一名 C++ 程序員,了解其某一特性的實現原理主要是為了避免錯誤地使用該特性。要達到這個目的,還要在了解實現原理的基礎上進行一些額外的開銷分析工作:
 
特性 時間開銷 空間開銷
EHDL 無運行時開銷 每“C++函數”一個 EHDL 對象,其中的 tblTryBlocks[] 成員僅在函數中包含至少一個 try 塊時使用。典型情況下小于 64 字節(jié)。

 

C++棧框架 極高的 O(1) 效率,每次調用時進行3次額外的整形賦值和一次 TLS 訪問。 每 調用兩個指針和一個整形開銷。典型情況下小于 16 字節(jié)。

 

step 跟蹤 極高的 O(1) 效率每次進出 try 塊或對象構造/析構一次整形立即數賦值。 無(已記入 C++ ??蚣苤械南鄳椖浚?。

 

異常的拋出、捕獲和?;赝?/td> 異常的拋出是一次 O(1) 級操作。在單個函數中進行捕獲和棧回退也均為 O(1) 操作。

但異常捕獲的總體成本為 O(m),其中 m 等于當前函數調用棧中,從拋出異常的位置到達匹配 catch 塊之間所經過的函數調用中,包含 try 塊(即:定義了有效 tblTryBlocks[])的函數個數。

棧回退的總成本為 O(n),其中 n 等于當前函數調用棧中,從拋出異常的位置到達匹配 catch 塊之間所經過的函數調用數。

在異常處理結束前,需保存異常對象及其析構函數指針和相應的 type_info 信息。

具體根據對象尺寸、編譯器選項(是否開啟 RTTI)及異常捕獲器的參數傳遞方式(傳值或傳址)等因素有較大變化。典型情況下小于 256 字節(jié)。

 

可以看出,在沒有拋出異常時,C++ 的異常處理機制是十分有效的。在有異常被拋出后,可能會依當前函數調用棧的情形進行若干次整形比較(try塊表匹配)操作,但這通常不會超過幾十次。對于大多數 15 年前的 CPU 來說,整形比較也只需 1 時鐘周期,所以異常捕獲的效率還是很高的。?;赝说男蕜t與 return 語句基本相當。

考慮到即使是傳統(tǒng)的函數調用、錯誤處理和逐級返回機制也不是沒有代價的。這些開銷在絕大多數情形下仍可以接受??臻g開銷方面,每“C++ 函數”一個 EHDL 結構體的引入在某些極端情形下會明顯增加目標文件尺寸和內存開銷。但是典型情況下,它們的影響并不大,但也沒有小到可以完全忽略的程度。如果正在為一個資源嚴格受限的環(huán)境開發(fā)應用程序,你可能需要考慮關閉異常處理和 RTTI 機制以節(jié)約存儲空間。

以上討論的是一種典型的異常機制的實現方式,各具體編譯器廠商可能有自己的優(yōu)化和改進方案,但總體的出入不會很大。

 

小節(jié)

異常處理是 C++ 中十分有用的嶄新特性之一。在絕大多數情況下,它們都有著優(yōu)異的表現和令人滿意的時空效率。異常處理本質上是另一種返回機制。但無論從軟件工程、模塊設計、編碼習慣還是時空效率等角度來說,除了在有充分文檔說明的前提下,偶爾可用來替代替代傳統(tǒng)的 setjmp/longjmp 功能外,應保證只將其用于程序的錯誤處理機制中。

此外,由于長跳轉的使用既易于出錯,又難于理解和維護。在編碼過程中也應當盡量避免使用。關于異常的一般性使用說明,請參考:代碼風格與版式:異常。

posted on 2011-12-13 18:23 鷹擊長空 閱讀(270) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产视频观看一区| 久久亚洲精品一区二区| 久久精品99| 亚洲一区二区三区四区中文 | 狠狠久久婷婷| 在线观看国产精品网站| 久久久免费精品视频| 欧美一级成年大片在线观看| 欧美在线视频在线播放完整版免费观看 | 亚洲国产日韩综合一区| 日韩视频永久免费观看| 亚洲一级二级在线| 久久精品国产综合精品| 久久久午夜视频| 亚洲丰满少妇videoshd| 最新日韩在线| 欧美一区二区三区的| 欧美成人自拍视频| 日韩视频免费看| 性做久久久久久久久| 欧美14一18处毛片| 国产嫩草一区二区三区在线观看 | 亚洲国产欧美日韩另类综合| 亚洲图片欧美日产| 免播放器亚洲| 日韩一级黄色大片| 久久精品视频一| 国产精品久久久久天堂| 在线日韩中文字幕| 欧美亚洲在线播放| 亚洲国产欧洲综合997久久| 亚洲一区区二区| 欧美精品成人91久久久久久久| 国产女人18毛片水18精品| 亚洲国产一区在线观看| 欧美在线观看日本一区| 日韩视频中文| 久久艳片www.17c.com| 国产精品永久| 夜夜嗨网站十八久久| 麻豆国产va免费精品高清在线| 亚洲视频一区在线| 欧美日韩精品免费看| 亚洲成在人线av| 久久青青草综合| 中文亚洲欧美| 欧美日韩另类一区| 亚洲精品一区二区三区99| 欧美 日韩 国产一区二区在线视频 | 久久精品国产精品亚洲精品| 亚洲免费观看视频| 欧美久久久久久久久久| 亚洲欧洲日本国产| 欧美风情在线观看| 久久综合电影| 亚洲高清免费| 你懂的视频一区二区| 久久蜜桃精品| 狠狠色噜噜狠狠色综合久| 久久久精彩视频| 午夜精品视频在线| 国产精品视频区| 亚洲一区精品在线| 亚洲欧美bt| 国产一区二区三区网站| 久久久久久久综合色一本| 亚洲欧美在线一区二区| 国产精品另类一区| 欧美一区二区在线看| 午夜精品美女自拍福到在线| 国产精品免费福利| 久久精品日韩| 久久一区二区精品| 99在线|亚洲一区二区| 日韩亚洲欧美一区二区三区| 欧美日韩一区二区视频在线观看| 一本色道久久综合狠狠躁篇的优点| 国产精品美女| 久久伊伊香蕉| 噜噜噜躁狠狠躁狠狠精品视频| 亚洲欧洲日产国码二区| 一本色道久久88综合日韩精品| 国产精品男女猛烈高潮激情| 久久久久久久久岛国免费| 久久久久免费观看| 99视频精品全部免费在线| 亚洲视频在线观看一区| 激情亚洲一区二区三区四区| 欧美激情第六页| 国产精品久久二区二区| 久久影视三级福利片| 欧美日韩国产va另类| 久久精品午夜| 欧美精品导航| 久久久精品国产免费观看同学| 免费试看一区| 性欧美1819sex性高清| 久久综合中文| 亚洲欧美国产视频| 久久一区二区视频| 亚洲一区欧美一区| 久久人人爽爽爽人久久久| 亚洲一品av免费观看| 久久久久**毛片大全| 亚洲视频 欧洲视频| 久久久亚洲精品一区二区三区| 一本久道综合久久精品| 久久成人在线| 亚洲一区成人| 免播放器亚洲一区| 久久精品视频导航| 欧美午夜一区二区三区免费大片 | 欧美另类变人与禽xxxxx| 久久国内精品自在自线400部| 欧美福利电影在线观看| 久久精品一区| 国产精品看片你懂得| 亚洲人成人77777线观看| 狠狠色狠狠色综合日日91app| 亚洲香蕉网站| 亚洲午夜高清视频| 欧美日韩日日夜夜| 美女诱惑黄网站一区| 国产亚洲精品久| 亚洲欧美精品中文字幕在线| 一本色道久久| 欧美精品一区二区三区在线播放| 免费在线观看一区二区| 国产在线视频不卡二| 亚洲欧美激情一区二区| 亚洲专区一区| 国产精品高清一区二区三区| 日韩视频一区二区三区| 一本一本久久a久久精品牛牛影视| 美女免费视频一区| 亚洲国产精品福利| 亚洲国产精品电影在线观看| 欧美亚洲色图校园春色| 久久福利影视| 国产三级精品在线不卡| 性做久久久久久久久| 久久久999精品| 一区免费观看| 久久综合九色九九| 欧美激情亚洲另类| 亚洲麻豆国产自偷在线| 欧美精彩视频一区二区三区| 亚洲欧洲精品一区二区精品久久久 | 欧美一级在线视频| 国产精品嫩草影院av蜜臀| 亚洲一品av免费观看| 欧美影院一区| 国产在线麻豆精品观看| 欧美不卡福利| 亚洲视频视频在线| 久久久久久网址| 亚洲韩国精品一区| 欧美精品在欧美一区二区少妇| 亚洲日本欧美天堂| 午夜精品福利一区二区蜜股av| 国产欧美日韩另类一区| 久久精品中文| 亚洲精品欧美极品| 欧美一级艳片视频免费观看| 国内外成人免费激情在线视频| 免费欧美在线视频| 一区二区高清在线| 老司机67194精品线观看| 亚洲欧洲一区二区在线播放| 国产精品激情偷乱一区二区∴| 久久久噜噜噜久久中文字免| 亚洲理伦电影| 久久久久久网址| 中文精品视频| 亚洲电影av| 国产精品美女午夜av| 久久精品天堂| 在线一区免费观看| 欧美成人三级在线| 香蕉av777xxx色综合一区| 亚洲黄色小视频| 国产欧美日韩另类一区| 欧美1区2区视频| 欧美一区二区三区在线看| 亚洲日本电影在线| 美女视频黄 久久| 亚洲综合三区| 日韩写真在线| 在线免费高清一区二区三区| 欧美色大人视频| 欧美丰满高潮xxxx喷水动漫| 性欧美精品高清| 在线亚洲欧美专区二区| 日韩一级黄色大片| 伊人久久久大香线蕉综合直播| 国产精品卡一卡二| 欧美精品在线观看| 美女爽到呻吟久久久久| 先锋影音久久久| 亚洲欧美日韩区|