欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
不要重載全局new

C++ 工程實(shí)踐(2):不要重載全局 ::operator new()

分類(lèi): c++ C++ 工程實(shí)踐 7542人閱讀 評論(25) 收藏 舉報

目錄(?)[+]

陳碩 (giantchen_AT_gmail)

Blog.csdn.net/Solstice

 

本文只考慮 Linux x86 平臺,服務(wù)端開(kāi)發(fā)(不考慮 Windows 的跨 DLL 內存分配釋放問(wèn)題)。本文假定讀者知道 ::operator new() 和 ::operator delete() 是干什么的,與通常用的 new/delete 表達式有和區別和聯(lián)系,這方面的知識可參考侯捷先生的文章《池內春秋》[1] ,或者這篇文章 。

C++ 的內存管理是個(gè)老生常談的話(huà)題,我在《當析構函數遇到多線(xiàn)程 》第 7 節“插曲:系統地避免各種指針錯誤”中簡(jiǎn)單回顧了一些常見(jiàn)的問(wèn)題以及在現代 C++ 中的解決辦法?;旧?,按現代 C++ 的手法(RAII)來(lái)管理內存,你很難遇到什么內存方面的錯誤?!皼](méi)有錯誤”是基本要求,不代表“足夠好”。我們常常會(huì )設法優(yōu)化性能,如果 profiling 表明 hot spot 在內存分配和釋放上,重載全局的 ::operator new() 和 ::operator delete() 似乎是一個(gè)一勞永逸好辦法(以下簡(jiǎn)寫(xiě)為“重載 ::operator new()”),本文試圖說(shuō)明這個(gè)辦法往往行不通。

內存管理的基本要求

如果只考慮分配和釋放,內存管理基本要求是“不重不漏”:既不重復 delete,也不漏掉 delete。也就說(shuō)我們常說(shuō)的 new/delete 要配對,“配對”不僅是個(gè)數相等,還隱含了 new 和 delete 的調用本身要匹配,不要“東家借的東西西家還”。例如:

  • 用系統默認的 malloc() 分配的內存要交給系統默認的 free() 去釋放;
  • 用系統默認的 new 表達式創(chuàng )建的對象要交給系統默認的 delete 表達式去析構并釋放;
  • 用系統默認的 new[] 表達式創(chuàng )建的對象要交給系統默認的 delete[] 表達式去析構并釋放;
  • 用系統默認的 ::operator new() 分配的的內存要交給系統默認的 ::operator delete() 去釋放;
  • 用 placement new 創(chuàng )建的對象要用 placement delete (為了表述方便,姑且這么說(shuō)吧)去析構(其實(shí)就是直接調用析構函數);
  • 從某個(gè)內存池 A 分配的內存要還給這個(gè)內存池。
  • 如果定制 new/delete,那么要按規矩來(lái)。見(jiàn) Effective C++ 相關(guān)條款。

做到以上這些不難,是每個(gè) C++ 開(kāi)發(fā)人員的基本功。不過(guò),如果你想重載全局的 ::operator new(),事情就麻煩了。

重載 ::operator new() 的理由

Effective C++ 第三版第 50 條列舉了定制 new/delete 的幾點(diǎn)理由:

  • 檢測代碼中的內存錯誤
  • 優(yōu)化性能
  • 獲得內存使用的統計數據

這些都是正當的需求,文末我們將會(huì )看到,不重載 ::operator new() 也能達到同樣的目的。

::operator new() 的兩種重載方式

1. 不改變其簽名,無(wú)縫直接替換系統原有的版本,例如:

#include

void* operator new(size_t size);

void operator delete(void* p);

用這種方式的重載,使用方不需要包含任何特殊的頭文件,也就是說(shuō)不需要看見(jiàn)這兩個(gè)函數聲明?!靶阅軆?yōu)化”通常用這種方式。

2. 增加新的參數,調用時(shí)也提供這些額外的參數,例如:

void* operator new(size_t size, const char* file, int line);  // 其返回的指針必須能被普通的 ::operator delete(void*) 釋放

void operator delete(void* p, const char* file, int line);   // 這個(gè)函數只在析構函數拋異常的情況下才會(huì )被調用

然后用的時(shí)候是

Foo* p = new (__FILE, __LINE__) Foo;   // 這樣能跟蹤是哪個(gè)文件哪一行代碼分配的內存

我們也可以用宏替換 new 來(lái)節省打字。用這第二種方式重載,使用方需要看到這兩個(gè)函數聲明,也就是說(shuō)要主動(dòng)包含你提供的頭文件?!皺z測內存錯誤”和“統計內存使用情況”通常會(huì )用這種方式重載。當然,這不是絕對的。

 

在學(xué)習 C++ 的階段,每個(gè)人都可以寫(xiě)個(gè)一兩百行的程序來(lái)驗證教科書(shū)上的說(shuō)法,重載 ::operator new() 在這樣的玩具程序里邊不會(huì )造成什么麻煩。

不過(guò),我認為在現實(shí)的產(chǎn)品開(kāi)發(fā)中,重載 ::operator new() 乃是下策,我們有更簡(jiǎn)單安全的辦法來(lái)到達以上目標。

現實(shí)的開(kāi)發(fā)環(huán)境

作為 C++ 應用程序的開(kāi)發(fā)人員,在編寫(xiě)稍具規模的程序時(shí),我們通常會(huì )用到一些 library。我們可以根據 library 的提供方把它們大致分為這么幾大類(lèi):

  1. C 語(yǔ)言的標準庫,也包括 Linux 編程環(huán)境提供的 Posix 系列函數。
  2. 第三方的 C 語(yǔ)言庫,例如 OpenSSL。
  3. C++ 語(yǔ)言的標準庫,主要是 STL。(我想沒(méi)有人在產(chǎn)品中使用 IOStream 吧?)
  4. 第三方的通用 C++ 庫,例如 Boost.Regex,或者某款 XML 庫。
  5. 公司其他團隊的人開(kāi)發(fā)的內部基礎 C++ 庫,比如網(wǎng)絡(luò )通信和日志等基礎設施。
  6. 本項目組的同事自己開(kāi)發(fā)的針對本應用的基礎庫,比如某三維模型的仿射變換模塊。

在使用這些 library 的時(shí)候,不可避免地要在各個(gè) library 之間交換數據。比方說(shuō) library A 的輸出作為 library B 的輸入,而 library A 的輸出本身常常會(huì )用到動(dòng)態(tài)分配的內存(比如 std::vector)。

如果所有的 C++ library 都用同一套內存分配器(就是系統默認的 new/delete ),那么內存的釋放就很方便,直接交給 delete 去釋放就行。如果不是這樣,那就得時(shí)時(shí)刻刻記住“這一塊內存是屬于哪個(gè)分配器,是系統默認的還是我們定制的,釋放的時(shí)候不要還錯了地方”。

(由于 C 語(yǔ)言不像 C++ 一樣提過(guò)了那么多的定制性,C library 通常都會(huì )默認直接用 malloc/free 來(lái)分配和釋放內存,不存在上面提到的“內存還錯地方”問(wèn)題?;蛘哂械目紤]更全面的 C library 會(huì )讓你注冊?xún)蓚€(gè)函數,用于它內部分配和釋放內存,這就就能完全掌控該 library 的內存使用。這種依賴(lài)注入的方式在 C++ 里變得花哨而無(wú)用,見(jiàn)陳碩寫(xiě)的《C++ 標準庫中的allocator是多余的 》。)

但是,如果重載了 ::operator new(),事情恐怕就沒(méi)有這么簡(jiǎn)單了。

重載 ::operator new() 的困境

首先,重載 ::operator new() 不會(huì )給 C 語(yǔ)言的庫帶來(lái)任何麻煩,當然,重載它得到的三點(diǎn)好處也無(wú)法讓 C 語(yǔ)言的庫享受到。

以下僅考慮 C++ library 和 C++ 主程序。

規則 1:絕對不能在 library 里重載 ::operator new()

如果你是某個(gè) library 的作者,你的 library 要提供給別人使用,那么你無(wú)權重載全局 ::operator new(size_t) (注意這是上面提到的第一種重載方式),因為這非常具有侵略性:任何用到你的 library 的程序都被迫使用了你重載的 ::operator new(),而別人很可能不愿意這么做。另外,如果有兩個(gè) library 都試圖重載 ::operator new(size_t),那么它們會(huì )打架,我估計會(huì )發(fā)生 duplicated symbol link error。干脆,作為 library 的編寫(xiě)者,大家都不要重載 ::operator new(size_t) 好了。

那么第二種重載方式呢?首先 ,::operator new(size_t size, const char* file, int line) 這種方式得到的 void* 指針必須同時(shí)能被 ::operator delete(void*) 和 ::operator delete(void* p, const char* file, int line) 這兩個(gè)函數釋放。這時(shí)候你需要決定,你的 ::operator new(size_t size, const char* file, int line) 返回的指針是不是兼容系統默認的 ::operator delete(void*)。

  • 如果不兼容(也就是說(shuō)不能用系統默認的 ::operator delete(void*) 來(lái)釋放內存),那么你得重載 ::operator delete(void*),讓它的行為與你的 operator new(size_t size, const char* file, int line) 匹配。一旦你決定重載 ::operator delete(void*),那么你必須重載 ::operator new(size_t),這就回到了情況 1:你無(wú)權重載全局 ::operator new(size_t)。
  • 如果選擇兼容系統默認的 ::operator delete(void*),那么你在 operator new(size_t size, const char* file, int line) 里能做的事情非常有限,比方說(shuō)你不能額外動(dòng)態(tài)分配內存來(lái)做 house keeping 或保存統計數據(無(wú)論顯示還是隱式),因為系統默認的 ::operator delete(void*) 不會(huì )釋放你額外分配的內存。(這里隱式分配內存指的是往 std::map<> 這樣的容器里添加元素。)

看到這里估計很多人已經(jīng)暈了,但這還沒(méi)完。

其次 ,在 library 里重載 operator new(size_t size, const char* file, int line) 還涉及到你的重載要不要暴露給 library 的使用者(其他 library 或主程序)。這里“暴露”有兩層意思:1) 包含你的頭文件的代碼會(huì )不會(huì )用你重載的 ::operator new(),2) 重載之后的 ::operator new() 分配的內存能不能在你的 library 之外被安全地釋放。如果不行,那么你是不是要暴露某個(gè)接口函數來(lái)讓使用者安全地釋放內存?或者返回 shared_ptr ,利用其“捕獲”deleter 的特性?聽(tīng)上去好像挺復雜?這里就不一一展開(kāi)討論了,總之,作為 library 的作者,絕對不要動(dòng)“重載 operator new()”的念頭。

事實(shí) 2:在主程序里重載 ::operator new() 作用不大

這不是一條規則,而是我試圖說(shuō)明這么做沒(méi)有多大意義。

如果用第一種方式重載全局 ::operator new(size_t),會(huì )影響本程序用到的所有 C++ library,這么做或許不會(huì )有什么問(wèn)題,不過(guò)我建議你使用下一節介紹的更簡(jiǎn)單的“替代辦法”。

如果用第二種方式重載 ::operator new(size_t size, const char* file, int line),那么你的行為是否惠及本程序用到的其他 C++ library 呢?比方說(shuō)你要不要統計 C++ library 中的內存使用情況?如果某個(gè) library 會(huì )返回它自己用 new 分配的內存和對象,讓你用完之后自己釋放,那么是否打算對錯誤釋放內存做檢查?

C++ library 從代碼組織上有兩種形式:1) 以頭文件方式提供(如以 STL 和 Boost 為代表的模板庫);2) 以頭文件+二進(jìn)制庫文件方式提供(大多數非模板庫以此方式發(fā)布)。

對于純以頭文件方式實(shí)現的 library,那么你可以在你的程序的每個(gè) .cpp 文件的第一行包含重載 ::operator new 的頭文件,這樣程序里用到的其他 C++ library 也會(huì )轉而使用你的 ::operator new 來(lái)分配內存。當然這是一種相當有侵略性的做法,如果運氣好,編譯和運行都沒(méi)問(wèn)題;如果運氣差一點(diǎn),可能會(huì )遇到編譯錯誤,這其實(shí)還不算壞事;運氣更差一點(diǎn), 編譯沒(méi)有錯誤,運行的時(shí)候時(shí)不時(shí)出現非法訪(fǎng)問(wèn),導致 segment fault;或者在某些情況下你定制的分配策略與 library 有沖突,內存數據損壞,出現莫名其妙的行為。

對于以庫文件方式實(shí)現的 library,這么做并不能讓其受惠,因為 library 的源文件已經(jīng)編譯成了二進(jìn)制代碼,它不會(huì )調用你新重載的 ::operator new(想想看,已經(jīng)編譯的二進(jìn)制代碼怎么可能提供額外的 new (__FILE__, __LINE__) 參數呢?)更麻煩的是,如果某些頭文件有 inline function,還會(huì )引起詭異的“串擾”。即 library 有的部分用了你的分配器,有的部分用了系統默認的分配器,然后在釋放內存的時(shí)候沒(méi)有給對地方,造成分配器的數據結構被破壞。

總之,第二種重載方式看似功能更豐富,但其實(shí)與程序里使用的其他 C++ library 很難無(wú)縫配合。

 

綜上,對于現實(shí)生活中的 C++ 項目,重載 ::operator new() 幾乎沒(méi)有用武之地,因為很難處理好與程序所用的 C++ library 的關(guān)系,畢竟大多數 library 在設計的時(shí)候沒(méi)有考慮到你會(huì )重載 ::operator new() 并強塞給它。

如果確實(shí)需要定制內存分配,該如何辦?

替代辦法

很簡(jiǎn)單,替換 malloc。如果需要,直接從 malloc 層面入手,通過(guò) LD_PRELOAD 來(lái)加載一個(gè) .so,其中有 malloc/free 的替代實(shí)現(drop-in replacement),這樣能同時(shí)為 C 和 C++ 代碼服務(wù),而且避免 C++ 重載 ::operator new() 的陰暗角落。

對于“檢測內存錯誤”這一用法,我們可以用 valgrind 或者 dmalloc 或者 efence 來(lái)達到相同的目的,專(zhuān)業(yè)的除錯工具比自己山寨一個(gè)內存檢查器要靠譜。

對于“統計內存使用數據”,替換 malloc 同樣能得到足夠的信息,因為我們可以用 backtrace() 函數來(lái)獲得調用棧,這比 new (__FILE__, __LINE__) 的信息更豐富。比方說(shuō)你通過(guò)分析 (__FILE__, __LINE__) 發(fā)現 std::string 大量分配釋放內存,有超出預期的開(kāi)銷(xiāo),但是你卻不知道代碼里哪一部分在反復創(chuàng )建和銷(xiāo)毀 std::string 對象,因為 (__FILE__, __LINE__) 只能告訴你最內層的調用函數。用 backtrace() 能找到真正的發(fā)起調用者。

對于“性能優(yōu)化”這一用法,我認為這目前的多線(xiàn)程開(kāi)發(fā)中,自己實(shí)現一個(gè)能打敗系統默認的 malloc 的內存分配器是不現實(shí)的。一個(gè)通用的內存分配器本來(lái)就有相當的難度,為多線(xiàn)程程序實(shí)現一個(gè)安全和高效的通用(全局)內存分配器超出了一般開(kāi)發(fā)人員的能力。 不如使用現有的針對多核多線(xiàn)程優(yōu)化的 malloc,例如 Google tcmalloc 和 Intel TBB 2.2 里的內存分配器 。好在這些 allocator 都不是侵入式的,也無(wú)須重載 ::operator new()。

為單獨的 class 重載 operator new() 有問(wèn)題嗎?

與全局 ::operator new() 不同,per-class operator new() 和 operator delete () 的影響面要小得多,它只影響本 class 及其派生類(lèi)。似乎重載 member operator new() 是可行的。我對此持反對態(tài)度。

如果一個(gè) class Node 需要重載 member operator new(),說(shuō)明它用到了特殊的內存分配策略,常見(jiàn)的情況是使用了內存池或對象池。我寧愿把這一事實(shí)明顯地擺出來(lái),而不是改變 new Node 的默認行為。具體地說(shuō),是用 factory 來(lái)創(chuàng )建對象,比如 static Node* Node::createNode() 或者 static shared_ptr Node::createNode();。

這可以歸結為最小驚訝原則:如果我在代碼里讀到 Node* p = new Node,我會(huì )認為它在 heap 上分配了內存,如果 Node class 重載了 member operator new(),那么我要事先仔細閱讀 node.h 才能發(fā)現其實(shí)這行代碼使用了私有的內存池。為什么不寫(xiě)得明確一點(diǎn)呢?寫(xiě)成 Node* p = Node::createNode(),那么我能猜到 Node::createNode() 肯定做了什么與 new Node 不一樣的事情,免得將來(lái)大吃一驚。

The Zen of Python 說(shuō) explicit is better than implicit,我深信不疑。

 

總結:重載 ::operator new() 或許在某些臨時(shí)的場(chǎng)合能應個(gè)急,但是不應該作為一種策略來(lái)使用。如果需要,我們可以從 malloc 層面入手,徹底而全面地替換內存分配器。

參考文獻:

池內春秋—— Memory Pool 的設計哲學(xué)與無(wú)痛運用 》,《程序員》2002 年第 9 期。

查看評論
17樓 FrankHB1989 2012-01-13 22:00發(fā)表 [回復]
不重載class scope operator new這種自我閹割的限制性手法居然成了符合最小驚訝?呵呵。我倒是挺愿意打那些既沒(méi)學(xué)好基本語(yǔ)義又懶得看清楚文檔的家伙們的臉的。
Explicit is better than implicit,雖然原意是沒(méi)什么錯,嘛,某些人就是擺脫不了用得羅嗦的原罪。要在這方面鼓吹這個(gè)是拉攏BASIC用戶(hù)么。
PS.“最小驚訝”實(shí)質(zhì)上就是對代碼閱讀者之間implicit的共識的依賴(lài)。
PS2.其實(shí)::operator new()不見(jiàn)得是重載,還有重寫(xiě)(覆蓋定義)。不過(guò)ISO C++為什么要給這里一個(gè)特例呢?又是值得呵呵的地方了。
16樓 saisons 2011-07-02 16:35發(fā)表 [回復]
不明白為什么反對局部重載new/delete,試想如下案例,應該如何是好?

假設我用C++為一個(gè)嵌入式系統寫(xiě)了一個(gè)靜態(tài)庫,想跟蹤一下內存分配的情況,應該怎么做呢?
- 不能改malloc,因為整個(gè)嵌入式系統是靜態(tài)聯(lián)編的,改掉malloc會(huì )影響整個(gè)系統
- 將new和delete替換為自定義的分配、銷(xiāo)毀函數,當合并以前寫(xiě)好的舊代碼會(huì )很累
- 系統的核心不開(kāi)源,無(wú)法插入其它的內存分析工具
15樓 lvdxzhou 2011-03-19 14:48發(fā)表 [回復]
[e01][e10]
本身做c++ 工作幾年鬼死神拆做了c# 、java ,一直想重做c++發(fā)現沒(méi)機會(huì )了。
貼帖園 http://www.tietie001.com. 歡迎回訪(fǎng)
14樓 kanchangcheng 2011-03-11 23:55發(fā)表 [回復]
[e01]
13樓 BuleRiver 2011-03-10 08:45發(fā)表 [回復]
就我觀(guān)察,重寫(xiě)operator new()的確并沒(méi)有實(shí)質(zhì)性的好處。
如果有需要,我也的確更新?lián)Q使用malloc()來(lái)實(shí)現相關(guān)的功能。
12樓 buaaji 2011-03-09 22:59發(fā)表 [回復]
規 則1里,在選擇兼容系統默認的 ::operator delete(void*)的情況下,如果不用stl里的map,而是自己實(shí)現一個(gè)map或者hashtable之類(lèi)的數據結構,這些數據結構完全用 malloc和free進(jìn)行內存分配和釋放。這樣的話(huà),在operator new里定義一個(gè)static的map/hashtable,貌似也可以保存統計數據。
Re: Solstice 2011-03-10 16:17發(fā)表 [回復]
回復 buaaji:你要不要重載 ::operator delete(void*) ?
Re: buaaji 2011-03-10 21:35發(fā)表 [回復]
回復 Solstice:需要重載::operator delete(void *)和::operator new (size_t size)
Re: Solstice 2011-03-10 22:15發(fā)表 [回復]
回復 buaaji:等于說(shuō)用你這個(gè)庫的人都被劫持了,不管愿不愿意都要從你的庫里的 ::operator new (size_t size) 分配內存。這是你的本意嗎?
11樓 hgdsnow 2011-03-09 18:25發(fā)表 [回復]
STL庫
10樓 iamybj 2011-03-09 08:52發(fā)表 [回復]
對于現實(shí)生活中的 C++ 項目,重載 ::operator new() 幾乎沒(méi)有用武之地,因為很難處理好與程序所用的 C++ library 的關(guān)系。如果確實(shí)需要,我們可以從 malloc 層面入手,徹底而全面地替換內存分配器。
--------------------
那干嘛不直接用C語(yǔ)言?
9樓 lovetheme 2011-02-25 19:30發(fā)表 [回復]
我 個(gè)人的理解,"new/delete內部在管理動(dòng)態(tài)內存的時(shí)候會(huì )調用malloc/free",仍然是一個(gè)工程實(shí)現 層面的經(jīng)驗性結論,畢竟還是缺乏標準層面嚴格的支撐,所以更完備安全的作法應該還是分別重載全局new/delete和malloc/free吧。
Re: Solstice 2011-02-25 21:34發(fā)表 [回復]
回 復 lovetheme:在現實(shí)中,我不擔心這個(gè)。只要 Linux 操作系統還是 C 語(yǔ)言寫(xiě)的,并以 C 語(yǔ)言提供系統接口(包括 libc),那么 new/delete 肯定最終會(huì )用 malloc/free 實(shí)現。如果什么都嚴格按標準來(lái),基本上寫(xiě)不出有用的程序。
8樓 apprentice_li 2011-02-23 16:18發(fā)表 [回復]
在你的替代方法中,如果第三方library用了new,delete,這部分內存豈不是不能統計到?而且第三方libarary new的內存交給你去free,可能也會(huì )出現問(wèn)題吧?
Re: Solstice 2011-02-23 16:47發(fā)表 [回復]
回復 apprentice_li: 1.能被統計到,這是鏈接層面的替換,不是代碼層面的。2. 不會(huì )有問(wèn)題,因為我們替換的是 glibc 的 malloc/free,程序里所有的內存分配都是從這個(gè)出入口走的。
Re: apprentice_li 2011-02-24 08:58發(fā)表 [回復]
回復 Solstice:謝謝,有機會(huì )試試
7樓 P_ghost 2011-02-23 15:01發(fā)表 [回復]
庫重載operator new是件很讓人郁悶的事。像GDI+就是這樣的,外部new GDI+對象,它卻會(huì )對其進(jìn)行垃圾回收,使用者在配對new/delete的時(shí)候還得考慮著(zhù)它是否已經(jīng)回收,深感氣憤??!
Re: chenyu2202863 2011-02-24 09:22發(fā)表 [回復]
回復 P_ghost:
庫內部使用類(lèi)會(huì )重載new
6樓 chenyu2202863 2011-02-23 09:42發(fā)表 [回復]
我會(huì )在寫(xiě)庫的時(shí)候重載類(lèi)成員operator new
5樓 lanzhengpeng2 2011-02-23 09:30發(fā)表 [回復]
"duplicated symbol link error"問(wèn)題好解決,作為庫設計者,不能再庫里引入new(size_t)這樣的符號,但不是不能在庫里引入內存分配的符號.因 此,解決方案就是將new(size_t)和delete(void*) inline.并使用宏給外部做選擇,是否要使用我這個(gè)庫的new和delete.
4樓 healer_kx 2011-02-22 21:18發(fā)表 [回復]
重載new,只不過(guò)在形式上提供了一種好的語(yǔ)法,確實(shí)未必有好的收獲。用的時(shí)候再#define一下,可能情況好很多。
我就是define了一個(gè)gc_new,然后寫(xiě)有g(shù)c的C++程序。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
關(guān)于new/delete 與free/malloc,指針與引用
[收藏]C++ Tips(2)
C++中new和delete導致的內存分配問(wèn)題詳解
C++中placement new操作符
[C++基礎]033
內存管理(整理筆記)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久