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

隨筆-341  評(píng)論-2670  文章-0  trackbacks-0
    復(fù)雜的東西寫(xiě)多了,如今寫(xiě)點(diǎn)簡(jiǎn)單的好了。由于功能上的需要,Vczh Library++3.0被我搞得很離譜。為了開(kāi)發(fā)維護(hù)的遍歷、減少粗心犯下的錯(cuò)誤以及增強(qiáng)單元測(cè)試、回歸測(cè)試和測(cè)試工具,因此記錄下一些開(kāi)發(fā)上的小技巧,以便拋磚引玉,造福他人。歡迎高手來(lái)噴,菜鳥(niǎo)膜拜。

    上一篇文章講到了如何檢查內(nèi)存泄露。其實(shí)只要肯用C++的STL里面的高級(jí)功能的話,內(nèi)存泄露是很容易避免的。我在開(kāi)發(fā)Vczh Library++ 3.0的時(shí)候,所有的測(cè)試用例都保證跑完了沒(méi)有內(nèi)存泄露。但是很可惜有些C++團(tuán)隊(duì)不能使用異常,更甚者不允許寫(xiě)構(gòu)造函數(shù)析構(gòu)函數(shù)之類(lèi),前一個(gè)還好,后一個(gè)簡(jiǎn)直就是在用C。當(dāng)然有這些變態(tài)規(guī)定的地方STL都是用不了的,所以我們更加需要扎實(shí)的基礎(chǔ)來(lái)開(kāi)發(fā)C++程序。

    今天這一篇主要還是講指針的問(wèn)題。因?yàn)樯弦黄恼乱还P帶過(guò),今天就來(lái)詳細(xì)講內(nèi)存泄漏或者野指針發(fā)生的各種情況。當(dāng)然我不可能一下子舉出全部的例子,只能說(shuō)一些常見(jiàn)的。

    一、錯(cuò)誤覆蓋內(nèi)存。

    之前提到的不能隨便亂memset其實(shí)就是為了避免這個(gè)問(wèn)題的。其實(shí)memcpy也不能亂用,我們來(lái)看一個(gè)例子,最簡(jiǎn)單的:
 1 #define MAX_STRING 20;
 2 
 3 struct Student
 4 {
 5   char name[MAX_STRING];
 6   char id[MAX_STRING];
 7   int chinese;
 8   int math;
 9   int english;
10 };

    大家對(duì)這種結(jié)構(gòu)肯定十分熟悉,畢竟是大學(xué)時(shí)候經(jīng)常要寫(xiě)的作業(yè)題……好了,大家很容易看得出來(lái)這其實(shí)是C語(yǔ)言的經(jīng)典寫(xiě)法。我們拿到手之后,一般會(huì)先初始化一下,然后賦值。
1 Student vczh;
2 memset(&vczh, 0sizeof(vczh));
3 strcpy(vczh.name, "vczh");
4 strcpy(vczh.id, "VCZH'S ID");
5 vczh.chinese=70;
6 vczh.math=90;
7 vczh.english=80;

    為什么要在這里使用memset呢?memset的用處是將一段內(nèi)存的每一個(gè)字節(jié)都設(shè)置成同一個(gè)數(shù)字。這里是0,因此兩個(gè)字符串成員的所有字節(jié)都會(huì)變成0。因此在memset了Student之后,我們通過(guò)正常方法來(lái)訪問(wèn)name和id的時(shí)候都會(huì)得到空串。而且如果Student里面有指針的話,0指針代表的是沒(méi)有指向任何有效對(duì)象,因此這個(gè)時(shí)候?qū)χ羔樦赶虻膶?duì)象進(jìn)行讀寫(xiě)就會(huì)立刻崩潰。對(duì)于其他數(shù)值,0一般作為初始值也不會(huì)有什么問(wèn)題(double什么的要小心)。這就是我們寫(xiě)程序的時(shí)候使用memset的原因。

    好了,如今社會(huì)進(jìn)步,人民當(dāng)家做主了,死程們?cè)僖膊恍枰艿娇蓯旱腃語(yǔ)言剝削了,我們可以使用C++!因此我們借助STL的力量把Student改寫(xiě)成下面這種帶有C++味道的形式:
1 struct Student
2 {
3   std::string name;
4   std::string id;
5   int chinese;
6   int math;
7   int english;
8 };

    我們?nèi)匀恍枰獙?duì)Student進(jìn)行初始化,不然三個(gè)分?jǐn)?shù)還是隨機(jī)值。但是我們又不想每一次創(chuàng)建的時(shí)候都對(duì)他們分別進(jìn)行賦值初始化城0。這個(gè)時(shí)候你心里可能還是想著memset,這就錯(cuò)了!在memset的時(shí)候,你會(huì)把std::string內(nèi)部的不知道什么東西也給memset掉。假如一個(gè)空的std::string里面存放的指針指向的是一個(gè)空的字符串而不是用0來(lái)代表空的時(shí)候,一下子內(nèi)部的指針就被你刷成0,等下std::string的析構(gòu)函數(shù)就沒(méi)辦法delete掉指針了,于是內(nèi)存泄露就出現(xiàn)了。有些朋友可能不知道上面那句話說(shuō)的是什么意思,我們現(xiàn)在來(lái)模擬一下不能memset的std::string要怎么實(shí)現(xiàn)。

    為了讓memset一定出現(xiàn)內(nèi)存泄露,那么std::string里面的指針必須永遠(yuǎn)都指向一個(gè)有效的東西。當(dāng)然我們還需要在字符串進(jìn)行復(fù)制的時(shí)候復(fù)制指針。我們這里不考慮各種優(yōu)化技術(shù),用最簡(jiǎn)單的方法做一個(gè)字符串出來(lái):
 1 class String
 2 {
 3 private:
 4   char* buffer;
 5 
 6 public:
 7   String()
 8   {
 9     buffer=new char[1];
10     buffer[0]=0;
11   }
12 
13   String(const char* s)
14   {
15     buffer=new char[strlen(s)+1];
16     strcpy(buffer, s);
17   }
18 
19   String(const String& s)
20   {
21     buffer=new char[strlen(s.buffer)+1];
22     strcpy(buffer, s.buffer);
23   }
24 
25   ~String()
26   {
27     delete[] buffer;
28   }
29 
30   String& operator=(const String& s)
31   {
32     delete[] buffer;
33     buffer=new char[strlen(s.buffer)+1];
34     strcpy(buffer, s.buffer);
35   }
36 };

    于是我們來(lái)做一下memset。首先定義一個(gè)字符串變量,其次memset掉,讓我們看看會(huì)發(fā)生什么事情:
1 string s;
2 memset(&s, 0sizeof(s));

    第一行我們構(gòu)造了一個(gè)字符串s。這個(gè)時(shí)候字符串的構(gòu)造函數(shù)就會(huì)開(kāi)始運(yùn)行,因此strcmp(s.buffer, "")==0。第二行我們把那個(gè)字符串給memset掉了。這個(gè)時(shí)候s.buffer==0。于是函數(shù)結(jié)束了,字符串的析構(gòu)函數(shù)嘗試delete這個(gè)指針。我們知道delete一個(gè)0是不會(huì)有問(wèn)題的,因此程序不會(huì)發(fā)生錯(cuò)誤。我們活生生把構(gòu)造函數(shù)賦值給buffer的new char[1]給丟了!鐵定發(fā)生內(nèi)存泄露!

    好了,提出問(wèn)題總要解決問(wèn)題,我們不使用memset的話,怎么初始化Student呢?這個(gè)十分好做,我們只需要為Student加上構(gòu)造函數(shù)即可:
1 struct Student
2 {
3   .//不重復(fù)那些聲明
4 
5   Student():chinese(0),math(0),english(0)
6   {
7   }
8 };

    這樣就容易多了。每當(dāng)我們定義一個(gè)Student變量的時(shí)候,所有的成員都初始化好了。name和id因?yàn)閟tring的構(gòu)造函數(shù)也自己初始化了,因此所有的成員也都初始化了。加入Student用了一半我們想再初始化一下怎么辦呢?也很容易:
1 Student vczh;
2 .//各種使用
3 vczh=Student();

    經(jīng)過(guò)一個(gè)等號(hào)操作符的調(diào)用,舊Student的所有成員就被一個(gè)新的初始化過(guò)的Student給覆蓋了,就如同我們對(duì)一個(gè)int變量重新賦值一樣常見(jiàn)。當(dāng)然因?yàn)楦鞣N復(fù)制經(jīng)常會(huì)出現(xiàn),因此我們也要跟上面貼出來(lái)的string的例子一樣,實(shí)現(xiàn)好那4個(gè)函數(shù)。至此我十分不理解為什么某些團(tuán)隊(duì)不允許使用構(gòu)造函數(shù),我猜就是為了可以memset,其實(shí)是很沒(méi)道理的。

    二、異常。

    咋一看內(nèi)存泄露跟異常好像沒(méi)什么關(guān)系,但實(shí)際上這種情況更容易發(fā)生。我們來(lái)看一個(gè)例子:
 1 char* strA=new char[MAX_PATH];
 2 if(GetXXX(strA, MAX_PATH)==ERROR) goto RELEASE_STRA;
 3 char* strB=new char[MAX_PATH];
 4 if(GetXXX(strB, MAX_PATH)==ERROR) goto RELEASE_STRB;
 5 
 6 DoSomething(strA, strB);
 7 
 8 RELEASE_STRB:
 9 delete[] strB;
10 RELEASE_STRA:
11 delete[] strA;

    相信這肯定是大家的常用模式。我在這里也不是教唆大家使用goto,不過(guò)對(duì)于這種例子來(lái)說(shuō),用goto是最優(yōu)美的解決辦法了。但是大家可以看出來(lái),我們用的是C++,因?yàn)檫@里有new。如果DoSomething發(fā)生了異常怎么辦呢?如果GetXXX發(fā)生了異常怎么辦呢?我們這里沒(méi)有任何的try-catch,一有異常,函數(shù)里克結(jié)束,兩行可憐的delete就不會(huì)被執(zhí)行到了,于是內(nèi)存泄漏發(fā)生了

    那我們?nèi)绾伪苊膺@種情況下的內(nèi)存泄露呢?一些可愛(ài)的小盆友可能會(huì)想到,既然是因?yàn)闆](méi)有catch異常才發(fā)生的內(nèi)存泄露,那我們來(lái)catch吧:
 1 char* strA=new char[MAX_PATH];
 2 try
 3 {
 4   if(GetXXX(strA, MAX_PATH)==ERROR) goto RELEASE_STRA;
 5   char* strB=new char[MAX_PATH];
 6   try
 7   {
 8     if(GetXXX(strB, MAX_PATH)==ERROR) goto RELEASE_STRB;
 9     DoSomething(strA, strB);
10   }
11   catch()
12   {
13     delete[] strB;
14     throw;
15   }
16 }
17 catch()
18 {
19   delete[] strA;
20   throw;
21 }
22 
23 RELEASE_STRB:
24 delete[] strB;
25 RELEASE_STRA:
26 delete[] strA;

    你能接受嗎?當(dāng)然是不能的。問(wèn)題出在哪里呢?因?yàn)镃++沒(méi)有try-finally。你看這些代碼到處都是雷同的東西,顯然我們需要編譯器幫我們把這些問(wèn)題搞定。最好的解決方法是什么呢?顯然還是構(gòu)造函數(shù)和析構(gòu)函數(shù)。總之記住,如果想要事情成對(duì)發(fā)生,那么使用構(gòu)造函數(shù)和析構(gòu)函數(shù)

    第一步,GetXXX顯然只能支持C模式的東西,因此我們要寫(xiě)一個(gè)支持C++的:
 1 bool GetXXX2(string& s)
 2 {
 3   char* str=new char[MAX_PATH];
 4   bool result;
 5   try
 6   {
 7     result=GetXXX(str, MAX_PATH);
 8     if(result)s=str;
 9   }
10   catch()
11   {
12     delete[] str;
13     throw;
14   }
15   delete[] str;
16   return result;
17 }

    借助這個(gè)函數(shù)我們可以看到,因?yàn)橛辛薌etXXX這種C的東西,導(dǎo)致我們多了多少麻煩。不過(guò)這總是一勞永逸的,有了GetXXX2和修改之后的DoSomething2之后,我們就可以用更簡(jiǎn)單的方法來(lái)做了:
1 string a,b;
2 if(GetXXX2(a) && GetXXX2(b))
3 {
4   DoSomething2(a, b);
5 }

    多么簡(jiǎn)單易懂。這個(gè)代碼在任何地方發(fā)生了異常,所有new的東西都會(huì)被delete。這就是析構(gòu)函數(shù)的一個(gè)好處。一個(gè)變量的析構(gòu)函數(shù)在這個(gè)變量超出了作用域的時(shí)候一定會(huì)被調(diào)用,無(wú)論代碼是怎么走出去的。

    今天就說(shuō)到這里了。說(shuō)了這么多還是想讓大家不要小看構(gòu)造函數(shù)和析構(gòu)函數(shù)。那種微不足道的因?yàn)橐恍〔糠植皇瞧款i的性能問(wèn)題而放棄構(gòu)造函數(shù)和析構(gòu)函數(shù)的做法,終究是要為了修bug而加班的。只要明白并用好了構(gòu)造函數(shù)、析構(gòu)函數(shù)和異常,那么C++的特性也可以跟C一樣清楚明白便于理解,而且寫(xiě)出來(lái)的代碼更好看的。大家期待第三篇哈。
posted on 2010-06-23 10:12 陳梓瀚(vczh) 閱讀(11742) 評(píng)論(23)  編輯 收藏 引用 所屬分類(lèi): C++實(shí)用技巧

評(píng)論:
# re: C++實(shí)用技巧(二) 2010-06-23 12:53 | OwnWaterloo
>>0指針代表的是沒(méi)有指向任何有效對(duì)象

空指針的二進(jìn)制表示并不一定是全0 。
浮點(diǎn)數(shù)也一樣, 0.0f, 0.0, 0.0lf的二進(jìn)制表示都不一定是全0。
所以, 即使是C語(yǔ)言, 欲使用memset去將指針初始化為空, 或者將浮點(diǎn)初始化為0, 都是不可移植的。


>>30 String& operator=(const String& s)
>>31 {
>>32 delete[] buffer;
>>33 buffer=new char[strlen(s.buffer)+1];
>>34 strcpy(buffer, s.buffer);
>>35 }

這個(gè)實(shí)現(xiàn)有問(wèn)題, 當(dāng)出現(xiàn)自賦值的時(shí)候:
String s;
s = s;
this->buffer和s.buffer是同一個(gè)指針。
32行delete之后, 已經(jīng)是dangling pointer。
33行傳遞給strlen, 34行傳遞給strcpy都是錯(cuò)誤的。


要么判斷自賦值的情況:
if (this!=&s)
{
delete[] buffer;
size_t len = strlen(s.buffer)+1;
buffer = new char[ len ];
memcpy(buffer, s.buffer, len );
}

但是, 如果new新的buffer時(shí)出現(xiàn)異常, 就會(huì)導(dǎo)致this有一個(gè)dangling pointer。
為了安全, 可以先new, 再delete:
size_t len = strlen(s.buffer)+1;
char* p = new char[len]; // 之后操作都不會(huì)產(chǎn)生異常
memcpy(p, s.buffer, len );
delete[] buffer;
buffer = p;

先new再delete也可以不用判斷自賦值的情況了。
  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 17:55 | zuhd
@OwnWaterloo
哥,你總是這么犀利,我給你留言看到?jīng)]?  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 18:33 | OwnWaterloo
@zuhd
剛發(fā)現(xiàn)…… 那一天收到的通知太多, 被我直接全部標(biāo)記為已讀, 然后忘了……
通常用同名gmail郵箱, qq不怎么用……
  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 18:42 | 陳梓瀚(vczh)
@OwnWaterloo
為了迅速說(shuō)明問(wèn)題,那個(gè)string其實(shí)還有很多其他的缺陷的……因?yàn)樵谥笾v構(gòu)造函數(shù)和析構(gòu)函數(shù)的一篇上會(huì)著重處理這種case。

話說(shuō)回來(lái),我上一篇提到了,這個(gè)系列是默認(rèn)你使用Visual C++的。  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 18:46 | 陳梓瀚(vczh)
@OwnWaterloo
話說(shuō)回來(lái),因?yàn)樵贑++里面,字面量“0”的確是代表空指針,因此如果空指針的二進(jìn)制真的不是0的話,我可以認(rèn)為是編譯器的bug。因?yàn)閺恼Z(yǔ)法上講,既然void* p=0;是對(duì)的,那么void* p=(void*)(int)0;也必須是對(duì)的。

除非從一開(kāi)始就有C++0x的nullptr。  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 19:25 | OwnWaterloo
@陳梓瀚(vczh)
無(wú)論是C還是C++, 說(shuō)的都是"編譯時(shí)可求出0值的常數(shù)是空指針常量"。
可以將空指針賦值給任意指針類(lèi)型的變量。
但并不保證賦值之后指針變量的二進(jìn)制表示也是全0。


從語(yǔ)法上講:
void* p = 0;
void* p=(void*)(int)0;
都是對(duì)的, 就像:

float f = 0;
float f = (float)(int)0;
而通常f的二進(jìn)制表示并不是全0。
這是因?yàn)榫幾g器是能看到這里的轉(zhuǎn)型動(dòng)作, 并加入適當(dāng)?shù)牟僮鳌?br>

但這樣寫(xiě)就是沒(méi)有保證的:
void* p;
memset(&p, 0, sizeof p);
memset函數(shù)中已經(jīng)不知道p的類(lèi)型, 只能將p當(dāng)作byte 數(shù)組。
就沒(méi)有機(jī)會(huì)為指針類(lèi)型作適當(dāng)?shù)恼{(diào)整。


再舉個(gè)例子:
class A {};
class B {};
class C : public A, public B {};

C c;
C* pc = &c;
A* pa = pc;
B* pb = pc;
assert( pc==pa && pc==pb);

因?yàn)榫幾g器知道pc,pa,pb的類(lèi)型。
所以無(wú)論是賦值還是比較, 都會(huì)插入適當(dāng)?shù)牟僮鳌?br>
而如果使用memset或者memcmp, 就掛了。


最后, 標(biāo)準(zhǔn)中有句話, 在calloc的腳注里。
The calloc function allocates space for an array
of nmemb objects, each of whose size is size.
The space is initialized to all bits zero.

Note that this need not be the same as the representation
of floating-point zero or a null pointer constant.
  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 20:40 | 付翔
指出個(gè) 小錯(cuò)誤
#define MAX_STRING 20; 不要分號(hào)   回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 21:49 | 陳梓瀚(vczh)
@OwnWaterloo
話說(shuō)回來(lái),那什么地方的空指針的二進(jìn)制不是0?  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 21:50 | 陳梓瀚(vczh)
@付翔
嗯嗯,這是個(gè)錯(cuò)誤。  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 21:52 | 陳梓瀚(vczh)
@OwnWaterloo
不過(guò)這個(gè)二進(jìn)制位不是0的事實(shí)更加反映出了構(gòu)造函數(shù)的重要性,memset更加不能隨便來(lái)了(當(dāng)然指的是非Visual C++的情況)  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 22:12 | OwnWaterloo
@陳梓瀚(vczh)
http://linuxdude.com/Steve_Sumit/C-faq/q5.17.html
整個(gè)第5章都是講null pointer的。
  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-23 22:35 | 陳梓瀚(vczh)
@OwnWaterloo
都是些從現(xiàn)在開(kāi)始見(jiàn)都沒(méi)見(jiàn)過(guò)的機(jī)器……  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-24 01:18 | 匿名
delete null
確定程序不會(huì)拋異常?  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-24 01:46 | 匿名(還是俺)
char* strA=new char[MAX_PATH];
這個(gè)也不能保證它一定不會(huì)拋異常。
new這個(gè)數(shù)組的時(shí)候,加入new到第M個(gè)(M小于MAX_PATH)時(shí)候拋出異常,這時(shí)候也會(huì)有內(nèi)存泄露咯  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-24 03:28 | 陳梓瀚(vczh)
@匿名(還是俺)
如果new一個(gè)東西還是敗了,那程序就直接log了崩潰了吧  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-24 10:25 | paul_simon
1 string s;
2 memset(&s, 0, sizeof(s));
//這里有個(gè)問(wèn)題想和博主探討,下文中提到的buffer是String的一個(gè)private成
//員,memset函數(shù)是不是該在String的成員函數(shù)里面調(diào)用,比如:
String::mems()
{
memset(buffer,0,sizeof(buffer));
}
//或者可否考慮在String::String()里加入memset函數(shù)
//QQ:29975723,謝謝  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-24 21:00 | 陳梓瀚(vczh)
@paul_simon
String當(dāng)然要為自己負(fù)責(zé)了,如果String自己覺(jué)得memset合適,那當(dāng)然可以。不過(guò)你那么搞有問(wèn)題,除非buffer是一個(gè)數(shù)組而不是指針。

但是外部不能memset掉string。  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-25 01:07 | paul_simon
@陳梓瀚(vczh)
String的構(gòu)造函數(shù)決定了buffer是個(gè)數(shù)組,這里的String和student是兩個(gè)不同的對(duì)象,String里的buffer成員不能被外部的memset所清零吧?
所以我說(shuō)的是
1 string s;
2 memset(&s, 0, sizeof(s));//這里的實(shí)質(zhì)不是是對(duì)buffer進(jìn)行清零嗎?  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-25 05:43 | 陳梓瀚(vczh)
@paul_simon
不是,因?yàn)轭?lèi)的私有部分是不透明的,所以你在外部操作的時(shí)候,不能以知道string的實(shí)現(xiàn)作為前提,人家改了怎么辦,你就要加班了。  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-28 02:11 | 球球
如果memset用在子類(lèi)的初始化時(shí)...  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-28 03:22 | 陳梓瀚(vczh)
@球球
子類(lèi)也不能假設(shè)父類(lèi)是如何實(shí)現(xiàn)的。  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-29 00:06 | chenq
用那么多代碼去try catch那個(gè)GetXXX,為什么不直接用smart pointer呢  回復(fù)  更多評(píng)論
  
# re: C++實(shí)用技巧(二) 2010-06-29 09:58 | 陳梓瀚(vczh)
@chenq
因?yàn)橛昧藄mart pointer就不能告訴人們C風(fēng)格的丑陋  回復(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>
            在线视频你懂得一区二区三区| 亚洲国产欧美一区二区三区久久| 久久综合狠狠| 亚洲网站视频福利| 亚洲午夜女主播在线直播| 宅男精品视频| 亚洲免费影视| 国产在线欧美| 亚洲电影av在线| 亚洲人成在线影院| 99一区二区| 亚洲综合三区| 久久久亚洲午夜电影| 蜜臀av在线播放一区二区三区| 牛夜精品久久久久久久99黑人| 久久久精品日韩欧美| 久久亚洲电影| 欧美日韩一区在线视频| 国产精品亚洲美女av网站| 国产一区高清视频| 亚洲精品乱码久久久久| 亚洲综合色激情五月| 久久天天狠狠| 亚洲精品国产精品乱码不99| 一本大道久久a久久精品综合| 亚洲在线一区| 免费高清在线视频一区·| 欧美精品综合| 国内精品久久久久久影视8| 亚洲国产精品一区二区久| 在线天堂一区av电影| 久久久999精品| 99精品国产在热久久婷婷| 小黄鸭精品密入口导航| 欧美国产日韩一区二区| 国产欧美欧美| av成人动漫| 卡通动漫国产精品| 亚洲天堂av在线免费| 久久综合伊人77777蜜臀| 欧美网站在线观看| 亚洲激情欧美| 久久九九全国免费精品观看| 亚洲精品综合精品自拍| 久久久亚洲人| 国产欧美日韩一区| 亚洲网站啪啪| 亚洲精品欧美日韩| 嫩草影视亚洲| 激情婷婷久久| 久久精选视频| 午夜精品亚洲一区二区三区嫩草| 欧美女同在线视频| 亚洲高清三级视频| 久久婷婷亚洲| 欧美一区观看| 国产视频一区在线观看| 亚洲性线免费观看视频成熟| 欧美制服丝袜第一页| 欧美网站大全在线观看| 日韩视频欧美视频| 欧美国产日韩二区| 久久一综合视频| 精品成人一区二区三区| 欧美一级淫片播放口| 亚洲视频在线观看一区| 欧美日韩精品免费| 亚洲午夜国产成人av电影男同| 亚洲激情影院| 欧美国产一区视频在线观看| 亚洲日本中文字幕免费在线不卡| 欧美ab在线视频| 久久久综合网站| 在线观看精品视频| 欧美成人中文字幕| 欧美福利视频在线观看| 亚洲美女啪啪| 一区二区av| 国产精品一区2区| 久久精品一区二区三区四区 | 欧美自拍偷拍午夜视频| 国精产品99永久一区一区| 久久久久国产精品一区| 久久成人综合视频| 亚洲国产精品久久久| 亚洲高清精品中出| 欧美日韩亚洲网| 香蕉成人久久| 久久国产精品毛片| 在线观看亚洲精品| 亚洲人成小说网站色在线| 欧美日韩一本到| 久久精品国产第一区二区三区最新章节 | 欧美日韩成人免费| 午夜精品一区二区三区电影天堂| 欧美在线视频不卡| 亚洲美女精品久久| 亚洲欧美日韩综合国产aⅴ| 中文无字幕一区二区三区| 亚洲欧美日韩区| 合欧美一区二区三区| 欧美国产视频在线观看| 欧美无砖砖区免费| 麻豆精品一区二区综合av| 欧美日韩色一区| 久久视频精品在线| 欧美日韩高清一区| 久久久久久久久久久成人| 在线观看亚洲专区| 亚洲视频网站在线观看| 亚洲另类自拍| 国产精品成人在线| 鲁大师成人一区二区三区| 欧美揉bbbbb揉bbbbb| 美女网站久久| 国产乱码精品一区二区三| 亚洲精品国产拍免费91在线| 狠狠做深爱婷婷久久综合一区| 亚洲精选视频免费看| 在线日韩av片| 欧美一区二区三区免费视| 亚洲午夜激情网页| 欧美经典一区二区| 欧美成人在线免费视频| 国产午夜精品一区二区三区视频 | 激情av一区| 亚洲欧美日韩视频二区| 在线综合亚洲欧美在线视频| 免费一级欧美片在线观看| 久久艳片www.17c.com| 国产日韩欧美夫妻视频在线观看| 一区二区三区四区五区精品| 夜夜嗨网站十八久久| 欧美电影在线播放| 亚洲激情视频| 夜夜精品视频一区二区| 欧美看片网站| 一本色道久久综合亚洲精品按摩 | 美女视频一区免费观看| 久久激情五月丁香伊人| 国产精品一区免费视频| 91久久精品国产91久久| 伊人久久婷婷色综合98网| 欧美影院成年免费版| 亚洲一级片在线看| 欧美搞黄网站| 欧美a级片网| 国产精品美女一区二区| 亚洲黄一区二区三区| 亚洲国产精品传媒在线观看| 欧美在线综合视频| 日韩午夜激情电影| 欧美日韩三区| 99精品国产福利在线观看免费 | 快播亚洲色图| 亚洲国产美国国产综合一区二区| 国内伊人久久久久久网站视频| 亚洲一区自拍| 亚洲欧美视频在线观看视频| 久久精品国产99精品国产亚洲性色| 久久久午夜电影| 国产三区精品| 欧美制服第一页| 久色婷婷小香蕉久久| 日韩一级免费观看| 亚洲欧美在线高清| 欧美在线亚洲在线| 欧美成人午夜免费视在线看片| 欧美综合国产精品久久丁香| 国产精品永久| 午夜老司机精品| 久久aⅴ国产紧身牛仔裤| 国产精品天天摸av网| 亚洲一区二区在线播放| 欧美一区二区| 国内一区二区三区| 欧美色道久久88综合亚洲精品| 一区二区欧美精品| 欧美亚洲综合在线| 伊人春色精品| 国产精品欧美一区喷水| 欧美在线播放高清精品| 蜜桃视频一区| 99国产一区| 伊人久久大香线蕉综合热线| 免费不卡视频| 一区二区三区日韩精品| 久久99伊人| 亚洲精品国产精品久久清纯直播 | 女同一区二区| 性久久久久久久| 黄色一区二区三区四区| 欧美国产日韩免费| 亚洲一区二三| 9久re热视频在线精品| 久久精品在线播放| 夜夜爽av福利精品导航| 国产一区二区欧美日韩| 国产乱码精品一区二区三区不卡 | 欧美日韩国产首页|