內(nèi)存管理

內(nèi)存布局

內(nèi)存分區(qū).png
  • stack區(qū):方法調(diào)用
  • heap區(qū) (堆區(qū)):alloc分配的一些對象
  • bss :未初始化的全局變量
  • data:已初始化的全局變量
  • text:程序代碼

內(nèi)存管理方案

  • TageedPointer:小對象绞幌,NSNumber等對象
  • NONPOINTER_ISA:64位 isa占64位啊奄,一般用30~40就夠用了菇夸,所以在剩余的位中做了內(nèi)存管理
  • 散列表 是復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
    ① 引用計數(shù)表
    ② 弱引用表

NONPOINTER_ISA

arm64結(jié)構(gòu)下是64位

  • 第一位indexed
    ① 0代表isa只是一個純的isa指針鞠眉,里面內(nèi)容指向當(dāng)前的類對象地址械蹋,
    ② 1代表不單單是isa指針哗戈,還有一些關(guān)于內(nèi)存管理的一些數(shù)據(jù)
  • 第二位has_assoc
    ① 0代表 沒有關(guān)聯(lián)對象
    ② 1代表 有關(guān)聯(lián)對象
  • 第三位has_cxx_dtor 當(dāng)前對象是否用到c++
    ① 0 沒有
    ② 1 有
  • shiftcls 4 ~ 36 33位 比特位是類對象的地址
    ① 當(dāng)前類對象的內(nèi)存地址
  • magic
  • weakly_referenced:是否有弱引用指針
  • deallocating:是否有dealloc的操作
  • has_sidetable_rc
    如果當(dāng)前的引用計數(shù)已經(jīng)達(dá)到上限唯咬,需要外掛一個has_sidetable_rc一個數(shù)據(jù)結(jié)構(gòu)去存儲相關(guān)的引用計數(shù)內(nèi)容
  • extra_rc 44~63 都是 extra_rc 引用計數(shù)
    引用計數(shù)在很小的范圍內(nèi)胆胰,會直接存儲到isa這里蜀涨,而不需要單獨的引用計數(shù)表來單獨存儲

散列表方式

sideTables()結(jié)構(gòu)

  • SideTable (數(shù)據(jù)結(jié)構(gòu))氧枣,由多個SideTable組成
  • 64個(非嵌入式系統(tǒng))

SIDETABLE

散列表方式.png

為什么不是一個SIDETABLE挑胸? 為什么要組成SIDETABLES呢?

  • 對象可能需要在不同線程操作創(chuàng)建移袍,這個時候進行操作的時候需要進行加鎖處理才能保證安全葡盗,這樣存在效率問題
  • 用戶的內(nèi)存空間需要4gb觅够,我們可以分配成千上萬的引用對象喘先,如果每個引用對象我們都要對齊進行引用計數(shù)改變窘拯,都操作這張表就會出現(xiàn)效率問題涤姊。如果一個對象操作這張表思喊,會加鎖下一個對象需要在等上一個對象的鎖加完以后在處理恨课,這就造成了效率低下的問題
  • 系統(tǒng)為了解決這個效率低下庄呈,系統(tǒng)給我們提供了一個分離鎖的概念
  • 系統(tǒng)為我們分配了8個這個表(64位),這樣就可以并發(fā)的去修改引用解決問題。

怎么樣實現(xiàn)快速分流盒刚?

SideTables的本質(zhì)是一張Hash表因块。
可能有64個SideTable存儲不同的引用計數(shù)表涡上、和弱引用表

什么是hash算法

對象指針可以作為Key通過hash函數(shù)計算計算出hash表中你的value值的下標(biāo)也就是索引吩愧。

hash查找的過程

給定值是對象內(nèi)存地址雁佳,目標(biāo)是數(shù)組下標(biāo)索引。

給了一個對象的內(nèi)存地址炸站,通過哈希函數(shù)的運算武契,得到了一個集合的下標(biāo)索引值

對象的內(nèi)存地址指針 % 數(shù)組的count就可以得到這個數(shù)組中的索引

這樣就查找速度快了

散列表方案設(shè)計的數(shù)據(jù)結(jié)構(gòu)

  • Spinlock_t
    ① 自旋鎖 是”忙等”的鎖届垫,如果當(dāng)前鎖已經(jīng)被其他線程獲取装处,那么當(dāng)前線程會不斷的探測這個鎖是否被其他線程釋放妄迁,如果釋放自己第一時間去獲取這個鎖
    ② 特點:適合輕量訪問(這個中+1 -1 計算邏輯不復(fù)雜的情況下稱之為輕量)
  • 信號量
    當(dāng)前線程獲取不到鎖的時候登淘,會把自己的線程阻塞休眠黔州,等這個鎖被釋放的時候,會喚醒它獲取這個鎖

引用計數(shù)表

實際上是一個refcountMap(hash表或者是字典)牲蜀,提高查找效率涣达,存儲查找都是hsah度苔,找到

  • size_t引用技術(shù)使用64位存儲的
  • 第一位是否有weak
  • 第二位是否deallocating

弱引用表

weak_table_t也是一張hash表林螃,

  • 通過對象指針,hash算法的到我們的weak_entry_t的表
  • weak_entry_t里面存儲的就是弱引用指針伏钠。

MRC和ARC

MRC

手動引用計數(shù)熟掂,進行內(nèi)存管理

  • alloc 分配一個對象的內(nèi)存空間
  • retain 引用計數(shù)加1
  • release 引用計數(shù)-1
  • retainCount 當(dāng)前引用計數(shù)的值
  • autorelease 會在autoreleasepool結(jié)束的時候赴肚,向其每一個對象發(fā)送release消息
  • dealloc 在MRC中需要顯示的調(diào)用super dealloc需要廢棄父類的相關(guān)成員變量

ARC

自動引用計數(shù)

  • ARC是由LLVM和Runtime協(xié)作完成
  • ARC中禁止手動調(diào)用retain、release刊愚、retainCount鸥诽、dealloc牡借、
    可以重寫dealloc但是不能調(diào)用super dealloc
  • ARC中新增weak炬藤、strong屬性關(guān)鍵字

ARC和MRC的區(qū)別

  • MRC是手動管理,ARC是LLVM和Runtime協(xié)作進行自動引用計數(shù)管理
  • MRC可以調(diào)用一些引用計數(shù)相關(guān)的+-1操作方法畅买,而ARC是不能的
  • ARC有weak和strong

引用計數(shù)管理

實現(xiàn)原理分析

alloc實現(xiàn)

  • 經(jīng)過一些列調(diào)用谷羞,最終調(diào)用了C函數(shù)calloc(初始化完成會自己置0 而malloc是垃圾數(shù)據(jù))湃缎。
  • 此時并沒有設(shè)置引用計數(shù)為1

retain實現(xiàn)

  • SideTable &table = SideTables()[this] 先獲取對應(yīng)的SideTable
  • size_t & refcntStorage = table.refcnts[this]; 獲取到SideTable中的引用計數(shù)值
  • refcntstorage += SIDE_TABLE_RC_ONE; 對其+1
    SIDE_TABLE_RC_ONE不是1嗓违,前兩個位置是存儲弱引用計數(shù)蹂季,和是否正在dealloc的偿洁,是后面62位涕滋,所以需要做一個偏移量宾肺。 所以說是4.

release實現(xiàn)

  • SideTable &table = SideTables()[this] 先獲取對應(yīng)的SideTable
  • RefcountMap:iterator it = table.refcnts.find(this); 獲取到SideTable中的引用計數(shù)值
  • it->second -= SIDE_TABLE_RC_ONE; 和retain正好相反

retainCount的實現(xiàn)

  • SideTable &table = SideTables()[this] 先獲取對應(yīng)的SideTable
  • size_t refcnt_result = 1; 聲明一個局部變量
  • RefcountMap::iterator it = table.refcnts.find(this) 獲取到SideTable中的引用計數(shù)值黔酥,剛?cè)lloc的對象其實里面是為0的
  • refcnt_result += it-> second >> SIDE_TABLE_RC_SHIFT 把查找的結(jié)果做一個向右偏移的操作跪者,然后在+1

dealloc的實現(xiàn)

  • 調(diào)用_objc_rootDealloc
  • rootDealloc
  • 是否直接釋放的判斷標(biāo)準(zhǔn)
    ① nonpointer_isa 是否是非指針型的isa指針
    ② weakly_referenced 是否有weak指針指向它
    ③ has_assoc 當(dāng)前對象是否有關(guān)連對象
    ④ has_cXX_dtor 是否使用了C++相關(guān)的代碼渣玲,是否ARC
    ⑤ has_sidetable_rc 是否是通過sidtable表來存儲的忘衍。
  • 以上都不是 就可以釋放,如果可以就使用c函數(shù)的free函數(shù)釋放
  • 如果不可以就使用object_dispose函數(shù)來進行后續(xù)的處理铅搓,然后結(jié)束


    dealloc的內(nèi)部實現(xiàn).png

OBJECT_DISPOSE實現(xiàn)

  • objc_destructInstance
  • C函數(shù)的free
  • 結(jié)束


    dealloc內(nèi)部實現(xiàn)中dispose函數(shù).png

OBJC_DESTRUCTINSTANCE的實現(xiàn)

  • 是否有C++或者是否有ARC
    YES object_cxxDestruct
    NO 調(diào)用AssociatedObjects
  • 如果沒有C++或者ARC 就調(diào)用AssociatedObjects方法
    YES _object_remove_assocations()
    NO clearDealloccating
  • _object_remove_assocations,以后還是沒有關(guān)聯(lián)對象那么都會調(diào)用clearDealloccating結(jié)束objc_destructInstance方法氢烘。


    objc_destructInstance函數(shù)實現(xiàn).png

CLEARDEALLOCCATING的實現(xiàn)

  • sidetable_clearDeallocating
  • weak_clear_no_lock
    將指向該對象的弱引用指針置為nil
  • table.refcnts.erase
    從引用計數(shù)表中擦除該對象的引用計數(shù)


    clearDealloccating.png

弱引用管理

弱引用調(diào)用棧

弱引用調(diào)用棧.png
  • 一個被聲明為__weak弱引用的指針,經(jīng)過編譯器編譯以后蜀踏,會調(diào)用objc_initWeak方法脓斩,經(jīng)過一系列的函數(shù)調(diào)用棧,會調(diào)用weak_register_no_lock這個函數(shù)吗讶,進行弱引用變量的添加照皆。
  • 具體添加的位置膜毁,是通過一個hash算法來進行進行位置查找的瘟滨,
  • 如果說我們查找位置當(dāng)中已經(jīng)有了當(dāng)前對象所有的弱引用數(shù)組杂瘸,我們新的弱引用變量添加到引用數(shù)組當(dāng)中败玉,如果沒有弱引用數(shù)組,那么就創(chuàng)建一個新的弱引用數(shù)組返干,然后第0個位置添加wek指針矩欠,后面的都置為0晚顷。

當(dāng)清除weak變量 通知設(shè)置指向為nil该默, 它是如何置nil的

如何將weak自動置為nil.png

完整過程

  • 通過被廢棄對象的指針經(jīng)過hash算法的到栓袖,求出弱引用數(shù)組對應(yīng)的數(shù)組索引位置裹刮,然后通過這個索引返回給對象我這個弱引用數(shù)組
  • 如果弱引用數(shù)組為空就調(diào)用捧弃,當(dāng)前對象违霞,沒有弱引用對象返回就成
  • 如果弱引用數(shù)組大于4調(diào)用entry->referrers如果小于4就使用entry->inline_referrers
  • 遍歷這個數(shù)組买鸽,如果數(shù)組中的指針就是被廢棄的弱引用指針那么就將其置為nil眼五。

總結(jié)

  • 當(dāng)一個對象唄dealloc之后看幼,dealloc內(nèi)部的實現(xiàn)會去調(diào)用弱引用清除這個函數(shù)
  • 然后函數(shù)會通過桌吃,當(dāng)前對象指針查找弱引用表 茅诱,把一個對象的所有弱引用表都拿出來瑟俭,是一個數(shù)組
  • 編譯所有這個數(shù)組當(dāng)中的弱引用指針分別置為nil

自動釋放池

自動釋放池的面試題.png

編譯器改寫

  • objc_autoreleasepoolPush()和objc_autoreleasePoolPop中間是代碼
  • push返回值是一個無類型的指針
  • objc_autoreleasePoolPop需要這個無類型指針作為標(biāo)記也就是push返回的無類型的指針


    autoreleasePool改寫.png

objc_autoreleasepoolPush和objc_autoreleasePoolPop的函數(shù)調(diào)用棧

  • 內(nèi)部會調(diào)用AutoreleasePoolPage::push方法
  • AutoreleasePoolPage::pop方法
    一次Pop當(dāng)然于一次批量的Pop操作(AutoreleasePool中的對象都會放入到自動釋放池中當(dāng)Pop之后失暴,AutoreleasePool中的對象的對象都會發(fā)送一次release消息所以是批量操作)

自動釋放池的數(shù)據(jù)結(jié)構(gòu)

  • 以棧為節(jié)點通過雙向鏈表的形式組合而成
  • 是和線程一一對應(yīng)的。

ATUORELEASEPOOLPAGE的數(shù)據(jù)結(jié)構(gòu)

  • id*next:當(dāng)前棧的空的位置
  • autoreleasePollPage * const parent; :鏈表的父指針
  • autoreleasePollPage *child; :鏈表的孩子指針
  • pthread_t const thread; : 與線程一一對應(yīng)的

AtuoreleasePoolPage::Push

AutoreleasePoolpagePush操作的原理.png

autorelease

autorelease的實現(xiàn)過程.png
  • 一個對象調(diào)用了autorelease方法矩肩,這個對象添加到next指針之后黍檩,next移動到新的位置刽酱,下一個調(diào)用autorelease方法的對象就會添加到這個位置

AtuoreleasePoolPage::Pop

  • 根據(jù)傳入的哨兵對象找到對應(yīng)位置
  • 給上次Push操作之后添加的對象依次發(fā)送release消息(next指針到哨兵對象之間的對象依次發(fā)送release消息)
  • 回退指針搭配正確位置


    AutoreleasePoolpagePop的原理操作.png

雙向鏈表的概念

雙向鏈表的結(jié)構(gòu).png

棧結(jié)構(gòu)概念

棧結(jié)構(gòu).png

面試題自動釋放池的實現(xiàn)結(jié)構(gòu)是什么?

以棧為節(jié)點通過雙向鏈表的形式組合而成

自動釋放池的總結(jié)

下面代碼什么時候釋放

viewdidload{
    NSMutableArray *array = [NSSmutableArray array];
}

在當(dāng)次runloop將要結(jié)束的時候調(diào)用AutoreleasePoolPage::Pop()

  • 每一次runloop循環(huán)將要結(jié)束的時候都會對前一次創(chuàng)建的autoreleasePool進行Pop操作殿怜,同時會Push進來一個新的autoreleasePool
  • viewdidload創(chuàng)建的對象,是在當(dāng)次runloop將要結(jié)束的時候麦轰,調(diào)用autoreleasePoolpage::Pop方法時候款侵,把對應(yīng)的array對象調(diào)用它的release方法新锈。

多次嵌套就是多次插入哨兵對象

關(guān)于autoreleasepool為和可以嵌套調(diào)用妹笆?

實際上多次嵌套插入哨兵對象,每次進行autoreleasePool的代碼塊創(chuàng)建的時候墩新,假如autoreleasePoolpage沒有滿的情況下海渊,系統(tǒng)就會在當(dāng)前autoreleasePoolpage棧中進行一次哨兵對象的插入臣疑,如果滿了會創(chuàng)建一個新的autoreleasePoolpage讯沈,然后當(dāng)前的autoreleasePoolpage中的child指針指向新創(chuàng)建的autoreleasePoolpage懒豹。

所以autoreleasepool可以多層嵌套調(diào)用

循環(huán)引用

三種循環(huán)引用:

  • 自循環(huán)引用
  • 相互循環(huán)引用
  • 多循環(huán)引用(大環(huán))

自循環(huán)引用

自循環(huán)引用.png

相互循環(huán)引用

相互循環(huán)引用.png

多循環(huán)引用(大環(huán))

大環(huán)循環(huán)引用(多循環(huán)引用).png

如何破除循環(huán)引用?

  • 避免產(chǎn)生循環(huán)引用
  • 在合適的時機手動斷環(huán)

具體解決方案:

  • __weak
  • __block
  • __unsafe_unretained

__WEAK 破解循環(huán)引用

__weak避免產(chǎn)生循環(huán)引用.png

__BLOCK破解* 破解循環(huán)引用

  • MRC __block修飾對象不會增加其引用計數(shù)驮樊,避免了循環(huán)引用
  • ARC __block修飾對象會被強引用囚衔,無法避免循環(huán)引用,需手動解環(huán)

__UNSAFE_UNRETAINED 破解循環(huán)引用

  • 修飾對象不會增加引用計數(shù)肥哎,避免了循環(huán)引用
  • 如果被修飾對象在某一時機被釋放,會產(chǎn)生懸垂指針杈女,懸垂指針又可能會出現(xiàn)不可預(yù)見的問題

循環(huán)引用示例

在開發(fā)過程中翰蠢,你遇到過哪些循環(huán)引用問題,你又是如何解決的趁尼?
  • Block的使用示例
  • NSTimer的循環(huán)引用問題
有一個頁面有一個banner滾動欄酥泞,每3秒滾到一次。一般有一個banner對象悯姊,VC對它強持有悯许,
banner對象的需求是每3秒滾動一次先壕。需要添加一個NSTimer谆甜,當(dāng)我向banner對象添加回調(diào)的時候,NSTimer會對banner對象施加一個強引用谆棺,這個時候就產(chǎn)生了相互循環(huán)引用問題改淑。

實際上溅固,NSTimer創(chuàng)建完成以后會有一個主線程RunLoop去強引用NSTimer強引用兰珍。就算是VC退出釋放掉掠河,那么banner對象也不會釋放,因為主線程runLoop強引用了這個對象爆捞。

NSTimer有重復(fù)煮甥,以及非重復(fù)定時器成肘,假如是非重復(fù)定時器斧蜕,那么在NSTimer回調(diào)完成以后設(shè)置無效并置nil批销,那么就破解了循環(huán)引用均芽。

假如NSTimer重復(fù)多次回調(diào)

第一種:在NSTimer和Banner之間設(shè)置一個中間對象骡技,這個中間對象分別弱引用NSTimer和banner對象。那么當(dāng)VC釋放掉囤萤,banner對象也就釋放掉了涛舍,NSTimer的回調(diào)會去中間對象唆途,而中間對象只要判斷banner對象為不為nil 如果為nil就直接無效化NSTimer肛搬。
NSTimer的循環(huán)引用問題.png

考點

  • 代理
  • block
  • NSTimer
  • 大環(huán)引用

MST

如果我們對一個類添加了關(guān)聯(lián)對象温赔,那么在這個類被釋放以后會清除掉這個關(guān)聯(lián)對象嗎?

會的待秃,因為系統(tǒng)在dealloc中釋放了關(guān)聯(lián)對象

關(guān)于autoreleasepool為和可以嵌套調(diào)用痹屹?

實際上多次嵌套插入哨兵對象志衍,每次進行autoreleasePool的代碼塊創(chuàng)建的時候楼肪,假如autoreleasePoolpage沒有滿的情況下淹辞,系統(tǒng)就會在當(dāng)前autoreleasePoolpage棧中進行一次哨兵對象的插入象缀,如果滿了會創(chuàng)建一個新的autoreleasePoolpage,然后當(dāng)前的autoreleasePoolpage中的child指針指向新創(chuàng)建的autoreleasePoolpage霞怀。

autoreleasePool的應(yīng)用場景

在for循環(huán)中alloc圖片數(shù)據(jù)等內(nèi)存消耗較大的場景手動插入autoreleasePool毙石。

autoreleasePool實現(xiàn)原理:

以棧為節(jié)點徐矩,通過雙向鏈表的形式組合而成的數(shù)據(jù)結(jié)構(gòu)

什么是ARC

ARC是由LLVM編譯器以及runtime協(xié)作來為我們實現(xiàn)自動引用計數(shù)的管理

為什么weak指針指向的對象在廢棄之后會被自動置為nil

當(dāng)對象在被廢棄之后滤灯,dealloc的內(nèi)部方法實現(xiàn)當(dāng)中會調(diào)用清除弱引用的方法鳞骤,然后在清除弱引用的方法中會通過hash算法來查找被廢棄對象在弱引用表當(dāng)中的位置來提取它所對的人用引用指針的列表數(shù)組,然后進行for循環(huán)遍歷顷帖,把每一個弱引用指針都置為nil

蘋果是如何實現(xiàn)AutoreleasePool

AutoreleasePool是以棧為節(jié)點,雙向鏈表形式來合成的數(shù)據(jù)結(jié)構(gòu)陈症。

什么是循環(huán)引用录肯?你遇到過哪些循環(huán)引用论咏,是怎么解決的颁井?

  • 自循環(huán)引用
  • 雙向循環(huán)引用
  • 大環(huán)引用
    比如說NStimer的循環(huán)引用厅贪。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市雅宾,隨后出現(xiàn)的幾起案子养涮,更是在濱河造成了極大的恐慌,老刑警劉巖眉抬,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贯吓,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜀变,警方通過查閱死者的電腦和手機悄谐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來库北,“玉大人情屹,你說我怎么就攤上這事±猓” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我珠移,道長勾习,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上漾唉,老公的妹妹穿的比我還像新娘场刑。我一直安慰自己,他們只是感情好科乎,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布空闲。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矫户。 梳的紋絲不亂的頭發(fā)上驱闷,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天扼菠,我揣著相機與錄音墨坚,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛寸癌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼责嚷!你這毒婦竟也來了揍异?” 一聲冷哼從身側(cè)響起戚嗅,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤醇份,失蹤者是張志新(化名)和其女友劉穎怖竭,沒想到半個月后广匙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抗碰,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡鞍爱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年佑笋,在試婚紗的時候發(fā)現(xiàn)自己被綠了关摇。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宪睹。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡胸蛛,死狀恐怖襟士,靈堂內(nèi)的尸體忽然破棺而出嗜历,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏刮吧。R本人自食惡果不足惜仅仆,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奢啥,春花似錦孝冒、人聲如沸穴店。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兑牡。三九已至洛勉,卻和暖如春陋气,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背洽糟。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工道偷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留履澳,地道東北人现横。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓示血,卻偏偏與公主長得像派昧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容