精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

充分理解 C/C++ 重要概念:運行時庫

開發
本文介紹了什么是C/C++運行時庫,運行時庫的主要的功能,各平臺的存在形式,以及開發要注意的問題,包括多實例問題和多版本問題等。

作者 | robot

在C/C++開發領域,運行時庫(Run Time Library)是一個非常重要且基礎的概念,但是相關的介紹文章卻很少,以至于對很多開發同學來說,這是一個偏神秘的存在,本文作者查閱了大量資料,并結合自己的理解,希望能夠通俗易懂的科普和揭秘一下這一領域,內容包括什么是C/C++運行時庫,它的主要功能,各平臺的存在形式,以及開發中要注意的問題。

一、認識C/C++運行時庫

1. 初識概念

你是否知道,我們開發的C/C++程序,在運行過程中,背后有一個基礎模塊,在默默提供著支持?

這背后的基礎模塊,也叫基礎庫,或運行時庫。

見下圖,支撐C/C++程序運行的,除了CPU/內存等硬件和操作系統之外,還有C/C++運行時庫:

那么,它具體在干什么呢?要理解這一概念,需要先從C/C++語言說起。

2. 編程語言

基本每種編程語言,包括C/C++語言,都包括兩個部分:

  • 語法部分:比如判斷、循環、定義變量、函數、類、注釋等,及一些內置類型。
  • 標準庫部分:該語言最常用的函數或類庫,比如輸入輸出、內存管理、字符串操作、數學函數、線程相關等。因為太基礎常用,所以被納入語言標準的一部分,稱為標準庫。

狹義的語言,僅僅是指語法部分,可稱之為語言本身;廣義的語言,是指語法部分+標準庫部分。

語言的標準庫+各種第三方庫,組成了我們程序中常見的各種庫。

C/C++運行時庫,就是在運行時,為語言的這兩部分提供基礎支持的庫。或者簡言之,C/C++運行時庫,就是C/C++程序在運行時依賴的基礎庫。

3. 其它語言的運行時庫

除了C/C++語言之外,其它語言其實也有自己的運行時庫。

比如Java,其運行時庫就是Java運行時環境(JRE),它包括Java虛擬機(JVM)和Java標準庫。

  • 比如Python,其運行時庫是指Python的解釋器 + Python標準庫。
  • 比如JavaScript,其運行時庫是指瀏覽器 + JavaScript解釋器。

總的來說,語言的運行時庫,就是為該語言編寫的程序,在運行時提供基礎支持的庫或環境。

二、C/C++運行時庫的功能

這一部分,我們來看看C/C++運行時庫的具體功能。

對于 C 和 C++,其實是兩種不同的語言,后者是在前者的基礎上擴展而來,它們的運行時庫,也是有兩個,我們分開來看看。

1. C運行時庫

C語言包括如下常用函數:

  • 輸入輸出函數,比如 printf、scanf、puts
  • 內存管理函數,比如 malloc、free、realloc
  • 文件系列函數,比如 fopen、fread、fwrite
  • 字符串相關函數,比如 strcpy、strcmp、strlen
  • 數學函數,比如 sin、cos、sqrt

這些函數是怎么實現的?是由誰提供的?

這些函數并不是由操作系統提供的,而是由C語言提供的,準確說是由C運行時庫提供的。

比如內存相關:

Linux系統原本提供的內存分配函數(也叫API),是brk、mmap等,而Windows系統提供的API是HeapAlloc、HeapFree、VirtualAlloc等,C語言(準確說是C運行時庫)把各操作系統提供的API封裝成統一的malloc、free。

如下圖,Linux下malloc調用系統API的堆棧:

Windows下malloc調用系統API的堆棧:

(事實上,malloc內部并不是簡單調用各系統API,而是做了一個內存池,小內存從池中分配,大內存調系統API)

對于文件:

  • C語言提供的fopen、fread、fwrite等,即FILE系列的緩沖文件,同樣是調用各平臺的系統API實現的。Linux下是調用open、write等非緩沖文件接口,Windows下是調用CreateFile、WriteFile等。
  • 除了上面說的平臺相關函數外,C運行時庫里,還有一些是平臺無關或關系不大的函數,比如字符串、數學相關函數等。
  • 另外C運行時庫為了支持程序的運行,還在統一的main函數前后做了一些邏輯,比如在main之前初始化一些全局變量、環境變量、命令行參數等,在main之后做一些資源的清理等。

總結一下,C運行時庫里提供了一系列常用的庫函數,包括把平臺相關函數封裝成統一的接口、平臺無關的,以及給我們提供了一個統一的main入口。

這些庫函數是事先編譯好的,通常隨編譯器一起發布,編譯器在編譯我們的程序時,自動幫我們做了鏈接,讓我們無感。

這也是為什么教科書說C語言是可移植語言的原因之一,因為這些跨平臺實現幫我們屏蔽了操作系統的差異,否則就需要調各操作系統的API,為不同平臺編寫不同的代碼了。

2. C++運行時庫

C++語言,是在C語言的基礎上提供了更多的功能特性,包括:

  • 語言本身,提供了類、多態、new/delete、異常、RTTI等。
  • 標準庫,提供了string、vector、list、map等各種容器和算法,以及輸入輸出流、智能指針、日期時間、線程相關等。

C++運行時庫,也是在C運行時庫的基礎上,為C++語言的這兩部分特性提供支持。

這些庫,語言提供者們幫我們實現好,放在一個動態庫或靜態庫中,編譯器最終做鏈接即可。

3. 總結一下

C/C++運行時庫的具體功能,綜合來看,有幾方面:

  • 支持程序的啟動和退出。包括main之前的全局變量、環境變量、命令行參數的初始化,和main之后的資源清理等。
  • 把一些平臺相關API封裝成統一的庫函數或類,便于我們跨平臺開發。
  • 其它常用功能的實現,封裝成函數或類。
  • 少量語言特性的支持,比如異常處理、RTTI等。

三、各平臺的C/C++運行時庫

前面介紹了C/C++運行時庫的通用概念和主要功能,這部分介紹一下在各平臺的具體存在形式。

為了更好的理解,在之前先介紹一下語言的標準和實現、動態庫與靜態庫,以及各平臺的庫文件格式。

1. 標準與實現

C和C++語言,都是只有一種標準,但有多種實現。

(1) 一種標準

即 ISO 的C/C++標準委員會制定的,但這個標準按時間順序,有多個版本,后一個版本在前一個版本基礎上改進,增加新的特性,同時也可能廢棄一些特性。

對于C語言,有C89/C90、C99、C11等;C++ 有 C++98、C++11、C++17、C++20 等。

C標準各版本簡介:

  • C89:ANSI C,第一個版本,是美國標準,有32個關鍵字,1989年
  • C90:和C89差不多,被國際ISO標準采納,1990年
  • C99:1999年發布,增加了多個特性,包括變長數組、inline關鍵字、//注釋、宏可變參數
  • C11:2011年發布,增加了多線程、內存對齊、Unicode等支持

C++標準各版本簡介:

  • C++98:C++的第一個標準版本,1998年由國際標準化組織(ISO)發布。
  • C++03:對C++98的一個小修訂,2003年發布。
  • C++11:2011年發布,重大更新,引入了很多新特性,如auto類型、范圍for循環、列表初始化、lambda表達式等。
  • C++14:2014年發布,對C++11的一個小修訂。
  • C++17:2017年發布,重大更新,引入了很多新特性,如結構化綁定、并行算法、模板參數自動推導等。
  • C++20:2020年發布。引入了很多新特性,如概念、協程、模塊等。

語言的標準,只是定義了語言的語法語義,以及有哪些頭文件、庫函數聲明等,但并不負責語言及這些庫函數的實現。

(2) 多種實現

語言的具體實現,是由各編譯器廠商完成的,包括語法語義的實現,和標準庫(運行時庫)的實現。

主要的有Linux下GNU的實現,Windows下的MSVC實現、以及LLVM的實現等,后文會具體介紹。

標準和實現的關系:

標準和實現不一定是完全一致的。比如某編譯器版本,可能對標準某特性的遵循不夠完善,也有可能某個編譯器先實現了某語言特性,然后才被納入標準。

2. 靜態庫與動態庫

與我們自己開發的庫是分為靜態庫與動態庫(也叫共享庫)一樣,C/C++運行時庫也是分為靜態庫與動態庫。比如在Linux平臺,靜態庫的后綴是.a,動態庫的后綴是.so。

  • 動態庫(共享庫)會被多個程序共享,好處是程序體積小,但缺點是運行時會多一些依賴。
  • 靜態庫正好相反,優點是運行時少依賴,但缺點是體積大,因為它被鏈接進可執行文件內部。

這些靜態庫或動態庫,是由廠商開發,提前編譯好,然后在編譯器編譯鏈接我們的程序時,自動鏈接進去。

3. 庫的文件格式

不同平臺的庫文件的二進制格式是不一樣的,文件名后綴也不一樣,為了避免在后文中部分同學疑惑,這里簡單介紹一下各平臺的庫文件格式。

可執行/庫文件格式,常見的就是三種,我列成一個表格:

注:

  • ELF:Executable and Linkable Format
  • PE:Portable Executable
  • Mach-O:Mach Object file format

4. 各平臺的具體實現

現在我們開始看看各平臺的具體實現,包括Linux平臺的GNU實現、Windows的實現、LLVM的實現、移動端的實現,以及其它嵌入式平臺的實現。

(1) GNU的實現

這是Linux后臺開發最常見的實現,其C運行時庫是GNU C Library,簡稱glibc。

  • GNU簡介:GNU是一個開源項目,全稱GNU's Not Unix,目標是開發一個操作系統,但由于其內核開發緩慢,我們實際上用到的是GNU的各種上層工具+Linux內核的結合,即GNU/Linux。
  • GNU項目具體包括:GCC(多種編譯器集合)、C庫(即glibc)、bash及各種命令行工具、編輯器等。我們日常接觸到的Linux,其實準確叫GNU/Linux,它是由GNU的各種上層工具+Linux內核組成。常見的各種Linux發行版(Ubuntu、Debian、CentOS等),都屬于GNU/Linux。

在Linux平臺,一個最簡單的C語言程序,在運行時會依賴哪些庫?

如下Hello World代碼:

// hello.c
#include <stdio.h>
int main() {
  printf("Hello World!\n");
  return 0;
}

使用 gcc 編譯,默認動態鏈接C運行時庫:

gcc hello.c -o hello

使用 ldd 命令查看依賴:

圖中的libc.so,即C的運行時庫。

其實嚴格來說,圖中的這三個庫,都是C程序的運行時庫,因為都是為程序的運行提供支持的。

順便看看文件大小:

Linux平臺,一個最簡單的C++程序,運行時會依賴哪些庫?

如下Hello World代碼:

// hello.cpp
#include <iostream>
int main() {
    std::cout << "Hello World!" << std::endl;
    return 0;
}

使用g++編譯,默認動態鏈接C/C++運行時庫:

g++ hello.cpp -o hello

用 ldd 命令查看依賴:

圖中的libstdc++.so,即C++的運行時庫。

附其它幾個庫簡介:

  • linux-vdso.so:虛擬庫,用于程序更高效的調用部分內核接口
  • libm.so:數學庫
  • libgcc_s.so:gcc的支持庫,用異常處理、RTTI等
  • ld-linux-x86-64.so:動態庫的加載器

庫的靜態與動態:

gcc、g++對于C/C++運行時庫,默認都是鏈接到其動態庫版,但也可以鏈接到其靜態庫版。

方法是:

  • C庫:gcc指定 -static 參數,這樣就可以鏈接到靜態庫 libc.a(事實上-static會把所有庫都靜態鏈接)
  • C++庫:g++ 指定 -static-libstdc++ 參數,這樣就可以鏈接到靜態庫版libstdc++.a

一個C程序使用 -static 靜態鏈接后,再看看其依賴的庫:

看看文件大小:

圖中看出,二進制不再依賴 libc.so 等庫了,這些庫被靜態鏈接到了可執行文件內部,體積也比之前大了。

(2) Windows的實現

在Windows平臺,微軟也實現了自己的C/C++運行時庫,一般隨Visual Studio發行。

一個最簡單的C/C++程序,使用vs2022編譯,默認指定/MD選項

用 Depends 工具查看其依賴的動態庫:

圖中的紅框部分,就是C/C++運行時庫。

在 Visual Studio 里,也可以設置動態或靜態鏈接運行時庫,方法是:

工程設置里(C/C++ -> 代碼生成 -> 運行庫)

  • /MT 多線程,即鏈接到靜態庫版
  • /MD 多線程DLL,即鏈接到動態庫版

另外還有個 /MTd 、/MDd 是用于調試版本。

當設置 /MT 即靜態鏈接后,就不再依賴這些庫了,如下圖:

hello.exe 文件體積從 13K 增加到 200K。

Windows平臺C/C++運行時庫動態版的文件名,不同的版本不一樣。

  • 早期的Vc6,是 msvcrt.dll 和 msvcp6.dll
  • 后來的版本,是 msvcrXX.dll 和 msvcpXX.dll(XX為版本號)
  • 從vs2015開始,微軟對其進行了重構,拆分成了ucrtbase.dll、msvcp140.dll、vcruntime140.dll等

(3) LLVM的實現

LLVM是一個較新的開源項目,可以說是專門為做編譯器相關而生,是一個更優的編譯器,各種配套的工具也比較完善,近年來越來越多的項目開始使用LLVM。

LLVM里用于C系語言(C、C++ 和 Objective-C)的編譯器前端,叫Clang。

除了做編譯器外,LLVM也開發了自己的C++庫,名字叫 libc++ (不同于GNU的 libstdc++)。LLVM也有自己的C庫,不過目前還不夠完善。

LLVM是一個跨平臺項目,支持多種平臺,包括Linux、Windows、macOS、iOS、Android等。

比如在Linux平臺,其C++運行時庫的文件名,動態庫版叫libc++.so,靜態庫版叫libc++.a。

(4) 移動端的實現

① iOS:

在iOS及macOS平臺,蘋果使用了LLVM的Clang作為Xcode內置的C/C++編譯器。

  • 其C運行時庫文件名是 libSystem.dylib,這個庫也包含了其它系統庫的功能。
  • 其C++運行時庫是 libc++.dylib 或 libc++.a。

② Android:

Android平臺一般使用Java或Kotlin開發,但在某些性能要求高的場合,也會使用C/C++開發,即NDK開發。

  • Android平臺的C運行時庫,叫Bionic libc,這是Google為Android專門開發的,比glibc更輕量,更適合移動設備。它同時提供了動態庫版本(libc.so)和靜態庫版本(libc.a)。
  • Android NDK的C++運行時庫,以前支持三種:libc++(即LLVM的)、libstdc++(即GNU的)和STLport,后來從NDK r18開始,只支持libc++了。

Android平臺里的 libc++ 庫的名字不太一樣,其動態庫版叫 libc++_shared.so,靜態庫版本叫 libc++_static.a。

是鏈接到靜態庫還是動態庫,可以在工程里指定,比如:

APP_STL := c++_shared

(5) 其它實現

除了上面常見的實現之外,還有一些早期的C/C++編譯器,也都帶有自己的運行時庫,比如Turbo C(很多人在學校里用的)、Borland C++(有人用過嗎)、C++Builder 等。

在一些嵌入式平臺,會使用一些更輕量的C運行時庫,主要有開源的 Newlib、uClibc、musl 等。

5. 總結一下

總結一個表格:

四、C/C++運行時庫相關問題

在開發中,我們常碰到的C/C++運行時庫相關問題,主要有多實例問題和多版本問題,下面分別介紹一下。

1. 運行時庫的多實例問題

為簡單起見,這里先只考慮單一開發環境下(即只有一個編譯器和運行時庫版本),進程內有多個運行時庫實例的問題。

先看一段代碼:

  • 動態庫導出一個接口函數:
char *GetData() {
  char *data = malloc(100);
  strcpy(data, "Hello World!");  // 僅演示,工作中不要用strcpy
  return data;
}
  • 主程序調用動態庫的接口函數:
int main() {
  char *data = GetData();
  free(data);
  return 0;
}

這段代碼,在有些平臺下運行(主要是Windows平臺),可能會crash。

為什么會crash,根本原因是和運行時庫的內存堆有關,下面具體講講。

(1) 單內存堆

在C運行時庫內部,有一個內存堆,也就是一個內存池,如下圖:

圖片圖片

大多數情況下,進程內只有一個C運行時庫實例,也就是只有一個內存堆。

上述代碼的依賴關系:

App.exe
  A.dll
  crt.dll

注:用縮進表示依賴關系,crt.dll 表示C運行時庫,相當于linux的 libc.so

A.dll 向 crt.dll 申請內存,用完后被 App.exe 再歸還給 crt.dll,這樣沒問題。

但是當進程內里有多個內存堆時,情況就不一樣了。

(2) 多內存堆

當進程內有多個C運行時庫實例時,就會有多個內存堆實例。

比如在Windows平臺,A.dll 設置 /MT 選項,即靜態鏈接C/C++運行時庫,主程序默認/MD選項,即動態鏈接C/C++運行時庫。

這時的依賴關系:

App.exe
  A.dll (靜態鏈接crt)
  crt.dll

這種場景下,A.dll 會從自己的內存堆中分配內存,用完后被 App.exe 歸還給了 crt.dll 的內存堆,這樣就引起了內存堆的結構異常,出現crash。

(3) 隱藏更深的情況

下面再看一種隱藏更深的情況,工作中更為常見。

動態庫 A 導出一個接口:

void GetData(std::string &data) {
  data = "Hello World!";  // 這句賦值內部,string會分配內存
}

在主程序或另一個動態庫中,調用動態庫 A 的接口:

void Test() {
  std::string data;
  GetData(data);
  // data析構,釋放string內部之前分配的內存,導致crash
}

上述代碼在靜態鏈接C/C++運行時庫時,會出現crash。

這里crash的本質,其實和前面一樣的,即一個模塊的分配的內存,交給了另一個模塊釋放。

除此之外,這個代碼,還有另一個風險,即如果兩個模塊使用了不同的編譯器或C++庫(比如一個使用GCC編譯,一個使用LLVM編譯),就可能會出現string的內存結構不一致而異常。

(4) 其它情況

在進程內有多C/C++運行時庫實例時,還有一些其它有問題的情況,比如跨模塊傳遞文件指針、跨模塊傳遞環境變量等。

比如:

// 動態庫導出該接口
void WriteData(FILE *file) {
  fwrite(...);
  fclose(file);
}

// 主程序里
int main() {
  FILE *file = fopen(...);
  WriteData(file);
  return 0;
}

(5) 總結一下

運行時庫的多實例,是由靜態鏈接C/C++運行時庫引起。在這種多實例場景下,一些不太好的代碼寫法,就會表現出問題。

如何避免這些問題,建議:

① 作為動態庫的設計者:

  • 盡量做到內存「誰分配誰釋放」的原則
  • 盡量避免庫間接口傳遞C/C++對象

這樣將會有更好的兼容性,即使在進程內有多個C/C++運行時庫時,也不會有問題。

② 作為App的總體設計者:

盡量保證進程內只有一份C/C++運行時庫實例

這樣也是會有更好的兼容性,能避免很多潛在問題。

如果用生活中的例子來類比,多運行時庫,就相當于一個公司對接了多個銀行,某個部門從 A 銀行借來的錢,被另一個部門還給了 B 銀行,這樣就引起了問題。

解決方法就是誰借的錢,誰來還,另外就是一個公司盡量只對接一個銀行。

關于運行時庫的多實例,幸運的是,大部分平臺的編譯器,已經幫我們規避了可能會導致運行時庫多實例的問題。

我簡單測了一下:

  • Linux平臺:對于主程序和動態庫,都默認動態鏈接C/C++運行時庫,主程序允許靜態鏈接C/C++運行時庫(方法是 -static 選項),動態庫不支持靜態鏈接C/C++運行時庫。
  • Windows平臺:對于主程序和動態庫,都支持動態或靜態鏈接C/C++運行時庫。
  • iOS和macOS平臺:不支持靜態鏈接C/C++運行時庫。
  • Android平臺:動態庫支持動態或靜態鏈接C++運行時庫,默認靜態鏈接,這可能導致風險,官方文檔提供了說明。

所以總結來看,這個問題主要是在Windows和Android平臺可能會出現,其它平臺編譯器不提供這種設置(特殊方法除外,比如自己開發一個運行時庫并靜態鏈接)。

如果你是做Windows和Android平臺開發,或者做跨平臺開發,涉及到這兩個平臺,就必須考慮運行時庫多實例問題,否則就可以不用太操心這個問題,編譯器已經防止了你犯錯。

2. 運行時庫的多版本問題

最后這一部分,簡單說說運行時庫的多版本問題。

和我們自己開發的軟件或庫,會不斷升級,會有多個版本一樣,C/C++運行時庫,也是在不斷升級,有很多個版本。

運行時庫的多版本,會引起兩個問題:

  • 編譯時用的庫,和運行時用的庫,版本不一致
  • 編譯同一個App的多個部分,用的庫版本不一致

后者在開發一些大型項目,不同模塊分屬不同團隊開發時,更容易出現。

這種不一致,可能會引起不匹配,從而產生各種問題。

(1) 問題現象

有些是在鏈接時不通過,提示符號沖突或找不到。比如:

undefined reference to `std::string::operator=(std::string const&)'
undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'

(也有可能是設置不統一引起)

有些是在啟動時,動態庫加載器檢測出異常,提示缺少符號,比如:

./test: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./test)
./test: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./test)
./test: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.22' not found (required by ./test)

有些是啟動時沒檢測出異常,而在運行時會有莫名其妙的問題。

(2) 解決方法

解決的方法,無它,只能是盡量保證一致,包括:

  • 編譯各模塊時,用的開發環境(包括編譯器版本+運行時庫版本+參數設置)一致。
  • 運行時和編譯時的庫環境一致。

具體怎么保持一致,有如下一些方法:

① 靜態鏈接

即不再依賴環境中的C/C++運行時庫,用體積換取少依賴。這個在Windows平臺較常用,Android平臺在只有一個動態庫時,官方也推薦靜態鏈接。

② 開發環境多版本共存時

選擇其中一個編譯器和C/C++運行時庫版本。比如在Windows平臺選擇工具集(v142/v143等),Linux平臺通過環境變量選擇GCC版本、Android平臺環境變量選擇NDK版本(r23/r25等)。

③ 運行環境多版本共存時

通過指定搜索路徑選擇其中一個版本。比如Linux平臺在二進制中指定(rpath)、環境變量指定(LD_LIBRARY_PATH)。

④ Docker

Linux平臺常用,即運行時提供一個隔離的干凈的環境。

五、總結

本文介紹了什么是C/C++運行時庫,運行時庫的主要的功能,各平臺的存在形式,以及開發要注意的問題,包括多實例問題和多版本問題等。遵守一些開發原則,以及保證運行時庫單實例、開發和運行環境的一致,可以避免很多潛在問題。

責任編輯:趙寧寧 來源: 騰訊技術工程
相關推薦

2010-01-27 14:14:48

C++程序運行時間

2011-08-19 15:05:29

異常處理

2023-11-21 16:31:51

C++語言

2024-12-09 13:00:00

C++類型安全

2011-12-27 09:39:12

C#運行時

2011-07-10 15:36:54

C++

2010-01-15 10:41:06

CC++

2015-07-20 15:44:46

Swift框架MJExtension反射

2014-09-02 10:39:53

Go語言C語言

2010-02-02 11:16:28

C++異常

2024-11-27 08:26:00

C++模板靜態

2011-05-18 17:33:15

CC++

2024-03-21 09:15:58

JS運行的JavaScrip

2023-12-18 11:15:03

2010-02-06 09:53:26

C++ void

2010-02-01 16:13:15

C++繼承

2009-02-10 09:03:59

動態語言CLRVB.NET

2019-07-12 09:30:12

DashboardDockerDNS

2021-09-11 15:38:23

容器運行鏡像開放

2023-11-28 11:51:01

C++函數
點贊
收藏

51CTO技術棧公眾號

亚洲 高清 成人 动漫| 91高清视频免费| 亚洲免费黄色录像| 欧美日韩在线资源| 国产呦萝稀缺另类资源| 欧美另类交人妖| 伊人久久一区二区三区| 亚洲国产成人二区| 国产欧美日韩亚州综合| 97国产精品视频人人做人人爱| 在线免费观看a级片| 少妇一区视频| 亚洲人成精品久久久久| 99国产高清| 久久亚洲天堂网| 久久国产成人精品| 亚洲成人精品视频| 亚洲色图38p| a视频在线免费看| 久久品道一品道久久精品| 国产噜噜噜噜噜久久久久久久久| 欧美视频一区二区在线| 国产精品主播在线观看| 色哦色哦哦色天天综合| 黄色一级片av| 加勒比一区二区三区在线| 国产一区二区视频在线| 青草成人免费视频| 欧美成人一区二区三区高清| 国产一区二区三区站长工具| 欧美一二三在线| 国内外免费激情视频| 日本一级理论片在线大全| 久久久久国产精品麻豆| 国产精品10p综合二区| 最新黄色网址在线观看| 国产亚洲毛片| 欧美激情中文字幕在线| 网爆门在线观看| 青青操综合网| 日韩欧美亚洲另类制服综合在线| 欧美一级裸体视频| 激情黄产视频在线免费观看| 亚洲欧美日韩国产一区二区三区| 久久国产精品精品国产色婷婷| 91久久久久国产一区二区| 亚洲欧美视频一区二区三区| 色综合久久88色综合天天看泰| 天天舔天天操天天干| 日韩深夜影院| 精品国精品国产| 丰满少妇中文字幕| 91精品店在线| 亚洲成年人网站在线观看| 亚洲精品国产精品国自产| 天堂中文资源在线| av一二三不卡影片| 99re在线观看视频| 国内老熟妇对白xxxxhd| 精品一区二区三区日韩| 国产精品视频专区| 中文字幕人妻一区二区在线视频 | 欧美男体视频| 精品国产乱码久久久久久天美| 菠萝蜜视频在线观看入口| 成人看av片| 中文字幕一区二区三| 亚洲一二三区在线| 天堂中文8资源在线8| 欧美国产精品v| 日韩高清国产精品| 九色视频成人自拍| 中文字幕不卡在线观看| 无码免费一区二区三区免费播放| 国产在线自天天| 神马久久久久久久久久久| 亚洲另类在线观看| 正在播放日韩欧美一页 | 四虎成人在线播放| 亚洲伦理久久| 欧美一区二区三区在线电影| 欧美成人女星排行榜| 五月天开心婷婷| 亚洲一区导航| 欧美电影免费观看完整版| 国产成人精品一区二区在线小狼| 一区二区三区免费在线看| 欧美日韩视频一区二区| 国产aⅴ爽av久久久久| 精品国产18久久久久久二百| 日韩精品中文字幕一区二区三区| 日韩无码精品一区二区| 色婷婷综合久久久久久| 中文字幕成人在线| wwwav国产| 欧美搞黄网站| 欧洲美女7788成人免费视频| 中文字幕av第一页| 精品一区二区三区在线观看国产| 99影视tv| 久久精品a一级国产免视看成人| 国产精品全国免费观看高清| 性生活免费观看视频| 黄网站在线免费看| 亚洲欧洲精品一区二区三区不卡| 国产精品视频网站在线观看| 色偷偷偷在线视频播放| 欧美日韩一区二区在线视频| 国产吃瓜黑料一区二区| 午夜先锋成人动漫在线| 日韩一区二区三区在线播放| 日本熟妇成熟毛茸茸| 日本不卡123| 成人精品视频99在线观看免费| 亚洲精品国产av| 久久精品视频免费| 黄色一级大片免费| 久久久久久久| 日韩欧美国产成人一区二区| 久久久久亚洲av成人无码电影| 亚洲男女av一区二区| 5252色成人免费视频| 一级片在线免费观看视频| aaa亚洲精品| 国产一区一区三区| 香蕉伊大人中文在线观看| 欧美电影一区二区三区| 久久久久麻豆v国产精华液好用吗| 9999国产精品| 欧美中文字幕视频| 亚洲伦理在线观看| 国产精品久久久久久久浪潮网站| 老太脱裤让老头玩ⅹxxxx| 欧美综合影院| 一区二区三区无码高清视频| 日韩成年人视频| 久久综合伊人| 国产精品国色综合久久| 欧美尤物美女在线| 色菇凉天天综合网| 鲁大师私人影院在线观看| 综合视频在线| 91九色蝌蚪国产| 成人在线免费公开观看视频| 欧美日韩一区二区三区在线免费观看| 欧美三级理论片| 亚洲综合图色| 国模吧一区二区三区| 国产成人精品av在线观| 国产精品麻豆欧美日韩ww| 男人舔女人下面高潮视频| 2020最新国产精品| 久久久精品久久| 亚洲天堂一二三| 国产精品网站在线观看| 亚洲成人福利在线观看| 国产亚洲一卡2卡3卡4卡新区 | 欧美日韩在线观看不卡| 成人中文字幕视频| 欧美高清性猛交| www久久久久久| 一区二区三区四区高清精品免费观看| 91亚洲精品久久久蜜桃借种| 青青草97国产精品麻豆| 国产精品老女人视频| 国产视频网址在线| 欧美中文字幕一区二区三区亚洲| 国内精品卡一卡二卡三| 老司机午夜精品视频在线观看| 日本一区免费看| 成人软件在线观看| 亚洲人成网站在线播| 日本一级淫片免费放| av亚洲精华国产精华精华| 9久久9毛片又大又硬又粗| 台湾色综合娱乐中文网| 日本在线观看天堂男亚洲| 台湾av在线二三区观看| 欧美性猛交xxxx免费看漫画| 日韩精品无码一区二区三区久久久| 亚洲一区区二区| 日本一区二区在线视频| 成人动漫视频在线观看| 欧美成人性生活| 成人乱码一区二区三区 | 久久国产精品无码网站| 在线精品亚洲一区二区| 蜜桃精品视频| 欧美激情亚洲综合一区| 五月激情婷婷网| 色综合久久久久综合体桃花网| 女人被狂躁c到高潮| 乱一区二区av| 久久www视频| 亚洲免费观看高清完整版在线观| 国产成人亚洲综合| 欧美性videos| 亚洲黄色在线观看| 艳妇乳肉豪妇荡乳av无码福利 | 麻豆免费在线视频| 日韩精品一区国产麻豆| 成人午夜淫片100集| 国产精品久久三区| 免费在线观看污网站| 欧美.www| 热re99久久精品国产99热| 精品国产一区二区三区2021| 久久久久久亚洲| 国产黄在线观看| 日韩一区二区免费高清| 亚洲一区 视频| 中文字幕不卡在线播放| 中文写幕一区二区三区免费观成熟| 亚洲女人av| 国产av第一区| 国产a久久精品一区二区三区| 国产在线观看一区二区三区 | 国产精品chinese在线观看| 国产成人精品免高潮费视频| 天堂av最新在线| 国产一区二区三区日韩欧美| 99久久99久久久精品棕色圆| 色屁屁一区二区| 国产中文字幕免费| 国产精品国产三级国产| 三级男人添奶爽爽爽视频| 九九视频精品免费| 亚洲一区二区三区av无码| 日韩激情在线| 欧美一区二区综合| 国产成人一二片| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 黄色录像免费观看| 久久亚洲综合色| 欧洲熟妇的性久久久久久| 另类成人小视频在线| 哪个网站能看毛片| 国产精品大片| 中文字幕第50页| 日韩精品一区二区久久| 久久成人资源| 久久午夜影院| 动漫美女被爆操久久久| 成人黄色理论片| 国产日韩欧美综合| jizz亚洲女人高潮大叫| 69久久夜色精品国产69| 久草在线视频福利| 欧美成人一区二区三区电影| 久久bbxx| 久久国产精彩视频| 午夜激情视频在线| 影音先锋欧美精品| avtt在线播放| 日韩在线视频免费观看| 午夜在线视频| 日韩亚洲欧美中文在线| 国产黄色片在线观看| 亚洲欧美在线免费观看| 免费人成在线观看网站| 亚洲精品中文字幕有码专区| 午夜福利视频一区二区| 亚洲福利在线看| 亚洲色图21p| 精品视频www| 欧美拍拍视频| 尤物99国产成人精品视频| 韩国三级在线观看久| 国产亚洲精品美女| 99riav在线| 精品国产视频在线| 亚洲男同gay网站| 久久久久国色av免费观看性色| 最爽无遮挡行房视频在线| 欧美大片大片在线播放| 大菠萝精品导航| 人人爽久久涩噜噜噜网站| 亚洲欧美一区二区三区| 国产成人精品免高潮费视频| 亚州一区二区三区| 国产精品影片在线观看| 国产精品国产三级在线观看| 亚洲综合中文字幕在线| 国偷自产av一区二区三区| 精品一区二区久久久久久久网站| 美国成人xxx| 亚洲高清在线播放| 欧美fxxxxxx另类| 精品久久久久久久久久中文字幕| 香蕉成人久久| 欧美成人三级在线播放| 久久精品理论片| 无码国产精品久久一区免费| 99久久99久久综合| 丰满的亚洲女人毛茸茸| 亚洲v日本v欧美v久久精品| 国产精品爽爽ⅴa在线观看| 91久久国产综合久久91猫猫| 日韩美女免费线视频| 亚洲国产天堂| 黄色国产精品一区二区三区| 欧美少妇性xxxx| 黄色一级片国产| 男人的天堂亚洲在线| 51自拍视频在线观看| 久久一夜天堂av一区二区三区| 免费成人深夜蜜桃视频| 亚洲国产欧美日韩另类综合 | 国产日韩欧美大片| 久久久久看片| 丰满少妇一区二区三区专区| 99re亚洲国产精品| 久热这里有精品| 欧美日韩综合在线| 天堂av在线资源| 欧美激情第6页| 成人乱码手机视频| 日韩电影免费观看高清完整| 99热这里只有精品8| 中文写幕一区二区三区免费观成熟| 国产精品人人做人人爽人人添| 亚洲欧美偷拍视频| 亚洲精品99久久久久中文字幕| 日韩精品分区| 91探花福利精品国产自产在线| av亚洲免费| 91网址在线播放| 97aⅴ精品视频一二三区| 国产在线拍揄自揄拍| 日韩亚洲电影在线| 日韩在线资源| 国产精品视频1区| 精品毛片免费观看| 欧美牲交a欧美牲交aⅴ免费下载| 不卡的看片网站| 国产成人精品亚洲男人的天堂| 欧美大片在线观看一区| 伊人影院在线视频| 亚洲自拍欧美色图| 久久久久久久久99精品大| 亚洲成人福利在线| 国产精品久久久久影院色老大| 成人黄色片在线观看| 国产亚洲欧美另类中文| 欧美二三四区| 亚洲国产精品综合| 免费看欧美女人艹b| 欧美xxxooo| 日韩一区二区三区免费观看| 羞羞电影在线观看www| 超碰97网站| 亚洲久久一区二区| 88久久精品无码一区二区毛片| 91搞黄在线观看| aaa在线观看| 92国产精品视频| 国内在线观看一区二区三区| www.com日本| 欧美日韩视频免费播放| 蜜桃视频在线免费| 国产精品一区久久久| 亚洲精品888| 国产免费一区二区三区最新6| 欧美日韩午夜剧场| 大片免费播放在线视频| 成人黄色在线播放| 欧美三级乱码| 偷拍女澡堂一区二区三区| 91国模大尺度私拍在线视频| 日本中文字幕伦在线观看| 亚洲va欧美va国产综合剧情| 在线国产日韩| 性猛交娇小69hd| 日韩一级片网站| 麻豆视频在线看| 在线免费一区| 国v精品久久久网| 国产成人一级片| 播播国产欧美激情| av在线亚洲色图| 热久久精品免费视频| 亚洲免费观看在线观看| 天天舔天天干天天操| 国产精品久久久久久婷婷天堂| 一本一道久久a久久精品蜜桃| 国产黄色三级网站| 欧美人狂配大交3d怪物一区| 黄网在线免费看| 香蕉久久夜色| 成人晚上爱看视频| 在线不卡免费视频| 国内免费久久久久久久久久久| blacked蜜桃精品一区| 亚洲热在线视频| 色丁香久综合在线久综合在线观看| 18在线观看的| 天堂社区 天堂综合网 天堂资源最新版 | xxxx日韩| 亚洲一区精品视频在线观看| 精品久久久在线观看|