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

Impossible is nothing  
  愛過知情重醉過知酒濃   花開花謝終是空   緣份不停留像春風來又走   女人如花花似夢
公告
日歷
<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
統計
  • 隨筆 - 8
  • 文章 - 91
  • 評論 - 16
  • 引用 - 0

導航

常用鏈接

留言簿(4)

隨筆分類(4)

隨筆檔案(8)

文章分類(77)

文章檔案(91)

相冊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

 

在為Linux開發應用程序時,絕大多數情況下使用的都是C語言,因此幾乎每一位Linux程序員面臨的首要問題都是如何靈活運用C編譯器。目前 Linux下最常用的C語言編譯器是GCC(GNU Compiler Collection),它是GNU項目中符合ANSI C標準的編譯系統,能夠編譯用C、C++和Object C等語言編寫的程序。GCC不僅功能非常強大,結構也異常靈活。最值得稱道的一點就是它可以通過不同的前端模塊來支持各種語言,如Java、 Fortran、Pascal、Modula-3和Ada等。

開放、自由和靈活是Linux的魅力所在,而這一點在GCC上的體現就是程序員通過它能夠更好地控制整個編譯過程。在使用GCC編譯程序時,編譯過程可以被細分為四個階段:

◆ 預處理(Pre-Processing)

◆ 編譯(Compiling)

◆ 匯編(Assembling)

◆ 鏈接(Linking)

Linux 程序員可以根據自己的需要讓GCC在編譯的任何階段結束,以便檢查或使用編譯器在該階段的輸出信息,或者對最后生成的二進制文件進行控制,以便通過加入不同數量和種類的調試代碼來為今后的調試做好準備。和其它常用的編譯器一樣,GCC也提供了靈活而強大的代碼優化功能,利用它可以生成執行效率更高的代碼。

GCC提供了30多條警告信息和三個警告級別,使用它們有助于增強程序的穩定性和可移植性。此外,GCC還對標準的C和C++語言進行了大量的擴展,提高程序的執行效率,有助于編譯器進行代碼優化,能夠減輕編程的工作量。

GCC起步

在學習使用GCC之前,下面的這個例子能夠幫助用戶迅速理解GCC的工作原理,并將其立即運用到實際的項目開發中去。首先用熟悉的編輯器輸入清單1所示的代碼:

清單1:hello.c

#include <stdio.h>
int main(void)
{
printf ("Hello world, Linux programming!n");
return 0;
}

然后執行下面的命令編譯和運行這段程序:

# gcc hello.c -o hello
# ./hello
Hello world, Linux programming!

從程序員的角度看,只需簡單地執行一條GCC命令就可以了,但從編譯器的角度來看,卻需要完成一系列非常繁雜的工作。首先,GCC需要調用預處理程序 cpp,由它負責展開在源文件中定義的宏,并向其中插入“#include”語句所包含的內容;接著,GCC會調用ccl和as將處理后的源代碼編譯成目標代碼;最后,GCC會調用鏈接程序ld,把生成的目標代碼鏈接成一個可執行程序。

為了更好地理解GCC的工作過程,可以把上述編譯過程分成幾個步驟單獨進行,并觀察每步的運行結果。第一步是進行預編譯,使用-E參數可以讓GCC在預處理結束后停止編譯過程:

#  gcc -E hello.c -o hello.i

此時若查看hello.cpp文件中的內容,會發現stdio.h的內容確實都插到文件里去了,而其它應當被預處理的宏定義也都做了相應的處理。下一步是將hello.i編譯為目標代碼,這可以通過使用-c參數來完成:

#  gcc -c hello.i -o hello.o

GCC默認將.i文件看成是預處理后的C語言源代碼,因此上述命令將自動跳過預處理步驟而開始執行編譯過程,也可以使用-x參數讓GCC從指定的步驟開始編譯。最后一步是將生成的目標文件鏈接成可執行文件:

#  gcc hello.o -o hello

在采用模塊化的設計思想進行軟件開發時,通常整個程序是由多個源文件組成的,相應地也就形成了多個編譯單元,使用GCC能夠很好地管理這些編譯單元。假設有一個由foo1.c和foo2.c兩個源文件組成的程序,為了對它們進行編譯,并最終生成可執行程序foo,可以使用下面這條命令:

#  gcc foo1.c foo2.c -o foo

如果同時處理的文件不止一個,GCC仍然會按照預處理、編譯和鏈接的過程依次進行。如果深究起來,上面這條命令大致相當于依次執行如下三條命令:

# gcc -c foo1.c -o foo1.o
# gcc -c foo2.c -o foo2.o
# gcc foo1.o foo2.o -o foo

在編譯一個包含許多源文件的工程時,若只用一條GCC命令來完成編譯是非常浪費時間的。假設項目中有100個源文件需要編譯,并且每個源文件中都包含 10000行代碼,如果像上面那樣僅用一條GCC命令來完成編譯工作,那么GCC需要將每個源文件都重新編譯一遍,然后再全部連接起來。很顯然,這樣浪費的時間相當多,尤其是當用戶只是修改了其中某一個文件的時候,完全沒有必要將每個文件都重新編譯一遍,因為很多已經生成的目標文件是不會改變的。要解決這個問題,關鍵是要靈活運用GCC,同時還要借助像Make這樣的工具。

警告提示功能

GCC包含完整的出錯檢查和警告提示功能,它們可以幫助Linux程序員寫出更加專業和優美的代碼。先來讀讀清單2所示的程序,這段代碼寫得很糟糕,仔細檢查一下不難挑出很多毛病:

◆main函數的返回值被聲明為void,但實際上應該是int;

◆使用了GNU語法擴展,即使用long long來聲明64位整數,不符合ANSI/ISO C語言標準;

◆main函數在終止前沒有調用return語句。

清單2:illcode.c

#include <stdio.h>
void main(void)
{
  long long int var = 1;
  printf("It is not standard C code!n");
}

下面來看看GCC是如何幫助程序員來發現這些錯誤的。當GCC在編譯不符合ANSI/ISO C語言標準的源代碼時,如果加上了-pedantic選項,那么使用了擴展語法的地方將產生相應的警告信息:

# gcc -pedantic illcode.c -o illcode
illcode.c: In function `main':
illcode.c:9: ISO C89 does not support `long long'
illcode.c:8: return type of `main' is not `int'

需要注意的是,-pedantic編譯選項并不能保證被編譯程序與ANSI/ISO C標準的完全兼容,它僅僅只能用來幫助Linux程序員離這個目標越來越近。或者換句話說,-pedantic選項能夠幫助程序員發現一些不符合 ANSI/ISO C標準的代碼,但不是全部,事實上只有ANSI/ISO C語言標準中要求進行編譯器診斷的那些情況,才有可能被GCC發現并提出警告。

除了-pedantic之外,GCC還有一些其它編譯選項也能夠產生有用的警告信息。這些選項大多以-W開頭,其中最有價值的當數-Wall了,使用它能夠使GCC產生盡可能多的警告信息:

# gcc -Wall illcode.c -o illcode
illcode.c:8: warning: return type of `main' is not `int'
illcode.c: In function `main':
illcode.c:9: warning: unused variable `var'

GCC給出的警告信息雖然從嚴格意義上說不能算作是錯誤,但卻很可能成為錯誤的棲身之所。一個優秀的Linux程序員應該盡量避免產生警告信息,使自己的代碼始終保持簡潔、優美和健壯的特性。

在處理警告方面,另一個常用的編譯選項是-Werror,它要求GCC將所有的警告當成錯誤進行處理,這在使用自動編譯工具(如Make等)時非常有用。如果編譯時帶上-Werror選項,那么GCC會在所有產生警告的地方停止編譯,迫使程序員對自己的代碼進行修改。只有當相應的警告信息消除時,才可能將編譯過程繼續朝前推進。執行情況如下:

# gcc -Wall -Werror illcode.c -o illcode
cc1: warnings being treated as errors
illcode.c:8: warning: return type of `main' is not `int'
illcode.c: In function `main':
illcode.c:9: warning: unused variable `var'

對Linux程序員來講,GCC給出的警告信息是很有價值的,它們不僅可以幫助程序員寫出更加健壯的程序,而且還是跟蹤和調試程序的有力工具。建議在用GCC編譯源代碼時始終帶上-Wall選項,并把它逐漸培養成為一種習慣,這對找出常見的隱式編程錯誤很有幫助。

在Linux 下開發軟件時,完全不使用第三方函數庫的情況是比較少見的,通常來講都需要借助一個或多個函數庫的支持才能夠完成相應的功能。從程序員的角度看,函數庫實際上就是一些頭文件(.h)和庫文件(.so或者.a)的集合。雖然Linux下的大多數函數都默認將頭文件放到/usr/include/目錄下,而庫文件則放到/usr/lib/目錄下,但并不是所有的情況都是這樣。正因如此,GCC在編譯時必須有自己的辦法來查找所需要的頭文件和庫文件。

GCC采用搜索目錄的辦法來查找所需要的文件,-I選項可以向GCC的頭文件搜索路徑中添加新的目錄。例如,如果在/home/xiaowp/include/目錄下有編譯時所需要的頭文件,為了讓GCC能夠順利地找到它們,就可以使用-I選項:

# gcc foo.c -I /home/xiaowp/include -o foo

同樣,如果使用了不在標準位置的庫文件,那么可以通過-L選項向GCC的庫文件搜索路徑中添加新的目錄。例如,如果在/home/xiaowp/lib/目錄下有鏈接時所需要的庫文件libfoo.so,為了讓GCC能夠順利地找到它,可以使用下面的命令:

# gcc foo.c -L /home/xiaowp/lib -lfoo -o foo

值得好好解釋一下的是-l選項,它指示GCC去連接庫文件libfoo.so。Linux下的庫文件在命名時有一個約定,那就是應該以lib三個字母開頭,由于所有的庫文件都遵循了同樣的規范,因此在用-l選項指定鏈接的庫文件名時可以省去lib三個字母,也就是說GCC在對-lfoo進行處理時,會自動去鏈接名為libfoo.so的文件。

Linux下的庫文件分為兩大類分別是動態鏈接庫(通常以.so結尾)和靜態鏈接庫(通常以.a 結尾),兩者的差別僅在程序執行時所需的代碼是在運行時動態加載的,還是在編譯時靜態加載的。默認情況下,GCC在鏈接時優先使用動態鏈接庫,只有當動態鏈接庫不存在時才考慮使用靜態鏈接庫,如果需要的話可以在編譯時加上-static選項,強制使用靜態鏈接庫。例如,如果在 /home/xiaowp/lib/目錄下有鏈接時所需要的庫文件libfoo.so和libfoo.a,為了讓GCC在鏈接時只用到靜態鏈接庫,可以使用下面的命令:

# gcc foo.c -L /home/xiaowp/lib -static -lfoo -o foo
代碼優化

代碼優化指的是編譯器通過分析源代碼,找出其中尚未達到最優的部分,然后對其重新進行組合,目的是改善程序的執行性能。GCC提供的代碼優化功能非常強大,它通過編譯選項-On來控制優化代碼的生成,其中n是一個代表優化級別的整數。對于不同版本的GCC來講,n的取值范圍及其對應的優化效果可能并不完全相同,比較典型的范圍是從0變化到2或3。

編譯時使用選項-O可以告訴GCC同時減小代碼的長度和執行時間,其效果等價于-O1。在這一級別上能夠進行的優化類型雖然取決于目標處理器,但一般都會包括線程跳轉(Thread Jump)和延遲退棧(Deferred Stack Pops)兩種優化。選項-O2告訴GCC除了完成所有-O1級別的優化之外,同時還要進行一些額外的調整工作,如處理器指令調度等。選項-O3則除了完成所有-O2級別的優化之外,還包括循環展開和其它一些與處理器特性相關的優化工作。通常來說,數字越大優化的等級越高,同時也就意味著程序的運行速度越快。許多Linux程序員都喜歡使用-O2選項,因為它在優化長度、編譯時間和代碼大小之間,取得了一個比較理想的平衡點。

下面通過具體實例來感受一下GCC的代碼優化功能,所用程序如清單3所示。

清單3:optimize.c

#include <stdio.h>

int main(void)

 double counter;  

double result;  

double temp;  

for (counter = 0;    counter < 2000.0 * 2000.0 * 2000.0  / 20.0 + 2020;    counter += (5 - 1) / 4)

{    temp = counter / 1979;    result  = counter;      } 

 printf("Result is %lfn", result); 

 return 0;

}

首先不加任何優化選項進行編譯:

# gcc -Wall optimize.c -o optimize

借助Linux提供的time命令,可以大致統計出該程序在運行時所需要的時間:

# time ./optimizeResult is 400002019.000000real    0m14.942suser    0m14.940ssys     0m0.000s

接下去使用優化選項來對代碼進行優化處理:

# gcc -Wall -O optimize.c -o optimize

在同樣的條件下再次測試一下運行時間:

# time ./optimizeResult is 400002019.000000real    0m3.256suser    0m3.240ssys     0m0.000s

對比兩次執行的輸出結果不難看出,程序的性能的確得到了很大幅度的改善,由原來的14秒縮短到了3秒。這個例子是專門針對GCC的優化功能而設計的,因此優化前后程序的執行速度發生了很大的改變。盡管GCC的代碼優化功能非常強大,但作為一名優秀的Linux程序員,首先還是要力求能夠手工編寫出高質量的代碼。如果編寫的代碼簡短,并且邏輯性強,編譯器就不會做更多的工作,甚至根本用不著優化。

 優化雖然能夠給程序帶來更好的執行性能,但在如下一些場合中應該避免優化代碼:

◆ 程序開發的時候 優化等級越高,消耗在編譯上的時間就越長,因此在開發的時候最好不要使用優化選項,只有到軟件發行或開發結束的時候,才考慮對最終生成的代碼進行優化。

◆ 資源受限的時候 一些優化選項會增加可執行代碼的體積,如果程序在運行時能夠申請到的內存資源非常緊張(如一些實時嵌入式設備),那就不要對代碼進行優化,因為由這帶來的負面影響可能會產生非常嚴重的后果。

◆ 跟蹤調試的時候 在對代碼進行優化的時候,某些代碼可能會被刪除或改寫,或者為了取得更佳的性能而進行重組,從而使跟蹤和調試變得異常困難。

調試

一個功能強大的調試器不僅為程序員提供了跟蹤程序執行的手段,而且還可以幫助程序員找到解決問題的方法。對于Linux程序員來講,GDB(GNU Debugger)通過與GCC的配合使用,為基于Linux的軟件開發提供了一個完善的調試環境。

默認情況下,GCC在編譯時不會將調試符號插入到生成的二進制代碼中,因為這樣會增加可執行文件的大小。如果需要在編譯時生成調試符號信息,可以使用GCC 的-g或者-ggdb選項。GCC在產生調試符號時,同樣采用了分級的思路,開發人員可以通過在-g選項后附加數字1、2或3來指定在代碼中加入調試信息的多少。默認的級別是2(-g2),此時產生的調試信息包括擴展的符號表、行號、局部或外部變量信息。級別3(-g3)包含級別2中的所有調試信息,以及源代碼中定義的宏。級別1(-g1)不包含局部變量和與行號有關的調試信息,因此只能夠用于回溯跟蹤和堆棧轉儲之用。回溯跟蹤指的是監視程序在運行過程中的函數調用歷史,堆棧轉儲則是一種以原始的十六進制格式保存程序執行環境的方法,兩者都是經常用到的調試手段。

GCC產生的調試符號具有普遍的適應性,可以被許多調試器加以利用,但如果使用的是GDB,那么還可以通過-ggdb選項在生成的二進制代碼中包含GDB專用的調試信息。這種做法的優點是可以方便GDB的調試工作,但缺點是可能導致其它調試器(如DBX)無法進行正常的調試。選項-ggdb能夠接受的調試級別和-g是完全一樣的,它們對輸出的調試符號有著相同的影響。

需要注意的是,使用任何一個調試選項都會使最終生成的二進制文件的大小急劇增加,同時增加程序在執行時的開銷,因此調試選項通常僅在軟件的開發和調試階段使用。調試選項對生成代碼大小的影響從下面的對比過程中可以看出來:

# gcc optimize.c -o optimize

# ls optimize -l-rwxrwxr-x  1 xiaowp   xiaowp  11649 Nov 20 08:53 optimize  (未加調試選項)

# gcc -g optimize.c -o optimize

# ls optimize -l-rwxrwxr-x  1 xiaowp   xiaowp  15889 Nov 20 08:54 optimize  (加入調試選項)

雖然調試選項會增加文件的大小,但事實上Linux中的許多軟件在測試版本甚至最終發行版本中仍然使用了調試選項來進行編譯,這樣做的目的是鼓勵用戶在發現問題時自己動手解決,是Linux的一個顯著特色。

下面還是通過一個具體的實例說明如何利用調試符號來分析錯誤,所用程序見清單4所示。

清單4:crash.c

#include <stdio.h>

 int main(void)

{  

int input =0;  

printf("Input an integer:");  

scanf("%d", input);  

printf("The integer you input is %dn", input); 

 return 0;

}

編譯并運行上述代碼,會產生一個嚴重的段錯誤(Segmentation fault)如下:

# gcc -g crash.c -o crash

# ./crashInput

an integer:10Segmentation fault

為了更快速地發現錯誤所在,可以使用GDB進行跟蹤調試,方法如下:

# gdb crashGNU gdb Red Hat Linux (5.3post-0.20021129.18rh)……(gdb)

當GDB提示符出現的時候,表明GDB已經做好準備進行調試了,現在可以通過run命令讓程序開始在GDB的監控下運行:

(gdb) runStarting program: /home/xiaowp/thesis/gcc/code/crashInput an integer:10Program received signal SIGSEGV, Segmentation fault.0x4008576b in _IO_vfscanf_internal () from /lib/libc.so.6

仔細分析一下GDB給出的輸出結果不難看出,程序是由于段錯誤而導致異常中止的,說明內存操作出了問題,具體發生問題的地方是在調用 _IO_vfscanf_internal ( )的時候。為了得到更加有價值的信息,可以使用GDB提供的回溯跟蹤命令backtrace,執行結果如下:

(gdb) backtrace

#0  0x4008576b in _IO_vfscanf_internal () from /lib/libc.so.6

#1  0xbffff0c0 in ?? ()

#2  0x4008e0ba in scanf () from /lib/libc.so.6

#3  0x08048393 in main () at crash.c:11

#4  0x40042917 in __libc_start_main () from /lib/libc.so.6

跳過輸出結果中的前面三行,從輸出結果的第四行中不難看出,GDB已經將錯誤定位到crash.c中的第11行了。現在仔細檢查一下:

(gdb) frame 3

#3  0x08048393 in main () at crash.c:1111       scanf("%d", input);

使用GDB提供的frame命令可以定位到發生錯誤的代碼段,該命令后面跟著的數值可以在backtrace命令輸出結果中的行首找到。現在已經發現錯誤所在了,應該將

scanf("%d", input);改為scanf("%d", &input);

完成后就可以退出GDB了,命令如下:

(gdb) quit

GDB的功能遠遠不止如此,它還可以單步跟蹤程序、檢查內存變量和設置斷點等。

調試時可能會需要用到編譯器產生的中間結果,這時可以使用-save-temps選項,讓GCC將預處理代碼、匯編代碼和目標代碼都作為文件保存起來。如果想檢查生成的代碼是否能夠通過手工調整的辦法來提高執行性能,在編譯過程中生成的中間文件將會很有幫助,具體情況如下:

# gcc -save-temps foo.c -o foo

# ls foo*foo  foo.c  foo.i  foo.s

GCC 支持的其它調試選項還包括-p和-pg,它們會將剖析(Profiling)信息加入到最終生成的二進制代碼中。剖析信息對于找出程序的性能瓶頸很有幫助,是協助Linux程序員開發出高性能程序的有力工具。在編譯時加入-p選項會在生成的代碼中加入通用剖析工具(Prof)能夠識別的統計信息,而- pg選項則生成只有GNU剖析工具(Gprof)才能識別的統計信息。

最后提醒一點,雖然GCC允許在優化的同時加入調試符號信息,但優化后的代碼對于調試本身而言將是一個很大的挑戰。代碼在經過優化之后,在源程序中聲明和使用的變量很可能不再使用,控制流也可能會突然跳轉到意外的地方,循環語句有可能因為循環展開而變得到處都有,所有這些對調試來講都將是一場噩夢。建議在調試的時候最好不使用任何優化選項,只有當程序在最終發行的時候才考慮對其進行優化。
上次的培訓園地中介紹了GCC的編譯過程、警告提示功能、庫依賴、代碼優化和程序調試六個方面的內容。這期是最后的一部分內容。
在將源代碼變成可執行文件的過程中,需要經過許多中間步驟,包含預處理、編譯、匯編和連接。這些過程實際上是由不同的程序負責完成的。大多數情況下GCC可以為Linux程序員完成所有的后臺工作,自動調用相應程序進行處理。

這樣做有一個很明顯的缺點,就是GCC在處理每一個源文件時,最終都需要生成好幾個臨時文件才能完成相應的工作,從而無形中導致處理速度變慢。例如,GCC 在處理一個源文件時,可能需要一個臨時文件來保存預處理的輸出、一個臨時文件來保存編譯器的輸出、一個臨時文件來保存匯編器的輸出,而讀寫這些臨時文件顯然需要耗費一定的時間。當軟件項目變得非常龐大的時候,花費在這上面的代價可能會變得很沉重。

解決的辦法是,使用Linux提供的一種更加高效的通信方式—管道。它可以用來同時連接兩個程序,其中一個程序的輸出將被直接作為另一個程序的輸入,這樣就可以避免使用臨時文件,但編譯時卻需要消耗更多的內存。

在編譯過程中使用管道是由GCC的-pipe選項決定的。下面的這條命令就是借助GCC的管道功能來提高編譯速度的:

# gcc -pipe foo.c -o foo

在編譯小型工程時使用管道,編譯時間上的差異可能還不是很明顯,但在源代碼非常多的大型工程中,差異將變得非常明顯。

文件擴展名

在使用GCC的過程中,用戶對一些常用的擴展名一定要熟悉,并知道其含義。為了方便大家學習使用GCC,在此將這些擴展名羅列如下:

.c C原始程序;

.C C++原始程序;

.cc C++原始程序;

.cxx C++原始程序;

.m Objective-C原始程序;

.i 已經過預處理的C原始程序;

.ii 已經過預處理之C++原始程序;

.s 組合語言原始程序;

.S 組合語言原始程序;

.h 預處理文件(標頭文件);

.o 目標文件;

.a 存檔文件。

GCC常用選項

GCC作為Linux下C/C++重要的編譯環境,功能強大,編譯選項繁多。為了方便大家日后編譯方便,在此將常用的選項及說明羅列出來如下:

-c 通知GCC取消鏈接步驟,即編譯源碼并在最后生成目標文件;

-Dmacro 定義指定的宏,使它能夠通過源碼中的#ifdef進行檢驗;

-E 不經過編譯預處理程序的輸出而輸送至標準輸出;

-g3 獲得有關調試程序的詳細信息,它不能與-o選項聯合使用;

-Idirectory 在包含文件搜索路徑的起點處添加指定目錄;

-llibrary 提示鏈接程序在創建最終可執行文件時包含指定的庫;

-O、-O2、-O3 將優化狀態打開,該選項不能與-g選項聯合使用;

-S 要求編譯程序生成來自源代碼的匯編程序輸出;

-v 啟動所有警報;

-Wall 在發生警報時取消編譯操作,即將警報看作是錯誤;

-Werror 在發生警報時取消編譯操作,即把報警當作是錯誤;

-w 禁止所有的報警。

小結

GCC 是在Linux下開發程序時必須掌握的工具之一。本文對GCC做了一個簡要的介紹,主要講述了如何使用GCC編譯程序、產生警告信息、調試程序和加快 GCC的編譯速度。對所有希望早日跨入Linux開發者行列的人來說,GCC就是成為一名優秀的Linux程序員的起跑線。


posted on 2006-02-25 12:29 笑笑生 閱讀(298) 評論(0)  編輯 收藏 引用 所屬分類: 編譯器
 
Copyright © 笑笑生 Powered by: 博客園 模板提供:滬江博客
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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视频超级精品| 亚洲福利国产精品| 麻豆av福利av久久av| 在线欧美影院| 国产精品久久久久三级| 欧美在线亚洲| 精品成人一区| 午夜精品久久久久久久蜜桃app| 国产自产精品| 亚洲二区视频在线| 久久久www成人免费精品| 欧美伦理91| 亚洲视频图片小说| 国产精品午夜电影| 久久久xxx| 亚洲二区在线| 亚洲欧洲日产国产综合网| 久久久久久久国产| 国产午夜精品麻豆| 久久频这里精品99香蕉| 欧美国产日韩在线观看| 在线观看国产成人av片| 国产一区二区av| 欧美日韩成人激情| 另类激情亚洲| 亚洲欧美影院| 亚洲欧美国产视频| 99视频在线观看一区三区| 日韩一级大片在线| 亚洲影音一区| 蜜桃久久精品一区二区| 亚洲欧洲日本在线| 久久久中精品2020中文| 亚洲一区二区3| 亚洲成色777777女色窝| 亚洲无毛电影| 欧美成人综合| 一本色道久久综合亚洲二区三区 | 国产精品videossex久久发布| 国产精品黄色| 欧美大片免费看| 一色屋精品视频在线观看网站| 久久乐国产精品| 久久精品人人| 亚洲手机在线| 蜜桃久久av| 国产日本欧美一区二区| 欧美国产日韩亚洲一区| 欧美成人精品1314www| 国产精品久久久久999| 国产精品免费久久久久久| 在线日韩欧美视频| 亚洲人成在线播放网站岛国| 日韩午夜电影av| 亚洲网站在线| 亚洲乱码国产乱码精品精可以看| 亚洲视频狠狠| 欧美va亚洲va国产综合| 在线观看日韩精品| 牛牛精品成人免费视频| 午夜亚洲伦理| 亚洲精品日本| 欧美 日韩 国产 一区| 国产精品国产三级欧美二区 | 欧美亚洲综合网| 久久久久久精| 欧美成人精精品一区二区频| 巨乳诱惑日韩免费av| 亚洲国产高清在线| 久久综合久久综合九色| 一区二区三区精品视频| 日韩午夜免费| 亚洲一区二区黄色| 亚洲日本va午夜在线影院| 香蕉尹人综合在线观看| 亚洲人成网站在线观看播放| 欧美国产视频在线| 欧美三区美女| 国产在线国偷精品产拍免费yy| 亚洲精品黄色| 亚洲激情第一页| 一区二区三区国产盗摄| 国产精品最新自拍| 鲁大师成人一区二区三区| 久久精品国产成人| 日韩亚洲国产欧美| 欧美三级视频在线| 久久久久久综合网天天| 亚洲午夜日本在线观看| 欧美一区国产一区| 在线观看日韩一区| 欧美综合国产| 亚洲欧美视频在线| 久久久久久91香蕉国产| 国产手机视频精品| 亚洲精品中文字幕在线| 性色一区二区| 欧美伦理91| 性欧美长视频| 蜜臀久久久99精品久久久久久| 亚洲精品黄网在线观看| 亚洲宅男天堂在线观看无病毒| 在线一区二区三区四区五区| 亚洲第一网站| 另类尿喷潮videofree| 亚洲精品美女| 欧美三级在线| 久久免费偷拍视频| 国产精品三上| 久久噜噜亚洲综合| 国产欧美一区二区精品忘忧草| 欧美亚洲视频| 午夜伦欧美伦电影理论片| 亚洲精品一区二区三区蜜桃久| 久久高清国产| 久久久99免费视频| 国产一区二区福利| 亚洲午夜未删减在线观看| 欧美一区2区三区4区公司二百| 亚洲午夜一区二区三区| 久久精品青青大伊人av| 国产精品色网| 欧美mv日韩mv国产网站| 国产综合在线看| 久久经典综合| 麻豆九一精品爱看视频在线观看免费 | 蜜臀av性久久久久蜜臀aⅴ| 欧美日韩一区二区在线观看视频| 亚洲第一级黄色片| 亚洲国产精品福利| 国产精品捆绑调教| 久久久久欧美| 国产欧美成人| 美玉足脚交一区二区三区图片| 久久手机免费观看| 欧美深夜福利| 久久成人国产精品| 美女露胸一区二区三区| 久久蜜桃精品| 欧美日韩午夜在线视频| 亚洲免费影视| 欧美激情视频在线播放 | 久久久久久高潮国产精品视| 精品成人免费| 国产精品欧美久久久久无广告| 一区二区三区久久久| 国产精品vvv| 久久视频国产精品免费视频在线| 亚洲精品乱码久久久久久黑人| 亚洲四色影视在线观看| 黑人巨大精品欧美黑白配亚洲| 欧美伊人久久| 欧美成人精品一区二区| 亚欧美中日韩视频| 国产精品露脸自拍| 欧美精品国产一区| 久久网站免费| 久久久久久尹人网香蕉| 欧美影院在线| 亚洲欧美一区二区三区久久| 亚洲精品视频免费在线观看| 日韩亚洲欧美中文三级| 一区二区三区欧美日韩| 99综合在线| 久久精品卡一| 欧美屁股在线| 国产精品视频自拍| 国产精品一区视频| 国产精品日日摸夜夜摸av| 亚洲第一区在线观看| 国产精一区二区三区| 国产精品毛片大码女人| 国产原创一区二区| 亚洲激情av在线| 久久夜色精品国产欧美乱极品| 亚洲国产一区视频| 久久久久一区二区| 91久久久久久久久| 国产欧美日韩一区二区三区| 香蕉av777xxx色综合一区| 性色av一区二区怡红| 一区二区三区日韩| 亚洲午夜精品久久久久久app| 另类专区欧美制服同性| 欧美日韩成人一区二区| 欧美天堂亚洲电影院在线观看| 在线观看欧美日本| 国内精品视频666| 亚洲一区精品电影| 亚洲一区二区三区在线| 亚洲日本在线视频观看| 久久久久久久久岛国免费| 欧美日韩国产一级| 欧美综合国产|