內(nèi)存管理

1.內(nèi)存布局

棧區(qū) 0x7
創(chuàng)建臨時(shí)變量時(shí)由編譯器自動(dòng)分配互婿,在不需要的時(shí)候自動(dòng)清除的變量的存儲(chǔ)區(qū)呛牲。
里面的變量通常是局部變量娘扩、函數(shù)參數(shù)等琐旁。在一個(gè)進(jìn)程中灰殴,位于用戶虛擬地址空間頂部的是用戶棧牺陶,編譯器用它來實(shí)現(xiàn)函數(shù)的調(diào)用。和堆一樣辣之,用戶棧在程序執(zhí)行期間可以動(dòng)態(tài)地?cái)U(kuò)展和收縮掰伸。

堆區(qū) 0x6
那些由 new alloc 創(chuàng)建的對象所分配的內(nèi)存塊,它們的釋放系統(tǒng)不會(huì)主動(dòng)去管怀估,由我們的開發(fā)者去告訴系統(tǒng)什么時(shí)候釋放這塊內(nèi)存(一個(gè)對象引用計(jì)數(shù)為0是系統(tǒng)就會(huì)回銷毀該內(nèi)存區(qū)域?qū)ο?狮鸭。一般一個(gè) new 就要對應(yīng)一個(gè) release。在ARC下編譯器會(huì)自動(dòng)在合適位置為OC對象添加release操作奏夫。會(huì)在當(dāng)前線程Runloop退出或休眠時(shí)銷毀這些對象怕篷,MRC則需程序員手動(dòng)釋放历筝。
堆可以動(dòng)態(tài)地?cái)U(kuò)展和收縮麻削。

靜態(tài)區(qū)(未初始化數(shù)據(jù)).bss
程序運(yùn)行過程內(nèi)存的數(shù)據(jù)一直存在叠荠,程序結(jié)束后由系統(tǒng)釋放

常量區(qū)(已初始化數(shù)據(jù)).data
專門用于存放常量鳖孤,程序結(jié)束后由系統(tǒng)釋放

代碼區(qū)
用于存放程序運(yùn)行時(shí)的代碼,代碼會(huì)被編譯成二進(jìn)制存進(jìn)內(nèi)存的程序代碼區(qū)

1.堆棧溢出的原因:
堆里面的放new出來的變量,一直往高地址延伸
棧區(qū)里面放了一些函數(shù),方法以及臨時(shí)變量,一直往低地址延伸
當(dāng)前APP進(jìn)程分配的內(nèi)存有限,會(huì)有一個(gè)臨界點(diǎn)
當(dāng)這兩個(gè)相遇就會(huì)形成堆棧溢出

2.內(nèi)存管理方案

TaggedPointer:小對象-NSNumber NSDate

  • 存儲(chǔ)小對象
  • 不是一個(gè)簡單的地址 包含了值和類型以及長度
    例如: 0x00000000012 (1代表值 2代表類型)
  • 速度特別快

NONPOINTER_ISA (非指針型isa)
是聯(lián)合體,被優(yōu)化成聯(lián)合體的位域 每一段里面都代表不同的含義
在不同的架構(gòu)下具體的分配是不一樣的
如果你重寫了allocWithZone后沒有調(diào)用父類 就不是被優(yōu)化過的ISA了

arm架構(gòu)下.png

nonpointer: 表示是否對 isa 指針開啟指針優(yōu)化
0:純isa指針
1:不止是類對象地址,isa 中包含了了類信息忍燥、對象的引?用計(jì)數(shù)等
has_assoc: 關(guān)聯(lián)對象標(biāo)志位哎甲,
0沒有
1存在
has_cxx_dtor: 該對象是否有 C++ 或者 Objc 的析構(gòu)器?,如果有析構(gòu)函數(shù),則需要做析構(gòu)邏輯, 如果沒有,則可以更更快的釋放對象
shiftcls: 存儲(chǔ)類指針的值。開啟指針優(yōu)化的情況下,在 arm64 架構(gòu)中有 33 位?用來存儲(chǔ)類指針
magic: 用于調(diào)試?判斷當(dāng)前對象是真的對象還是沒有初始化的空間 weakly_referenced: 標(biāo)志對象是否被指向或者曾經(jīng)指向?一個(gè) ARC 的弱變量,沒有弱引用的對象可以更快釋放。
deallocating: 標(biāo)志對象是否正在釋放內(nèi)存
has_sidetable_rc:當(dāng)對象引?計(jì)數(shù)大于 10 時(shí)德崭,則需要借?該變量存儲(chǔ)進(jìn)位
extra_rc:當(dāng)表示該對象的引?計(jì)數(shù)值兽狭,實(shí)際上是引用計(jì)數(shù)值減 1, 例如有咨,如果對象的引用計(jì)數(shù)為 10似忧,那么 extra_rc 為 9。如果引?用計(jì)數(shù)?大于 10, 則需要使用到上面的 has_sidetable_rc。

散列表(SideTable):

SideTable 其實(shí)是一個(gè) hash 表梢睛,下面掛了很多的 SideTable藏畅,SideTable 包括自旋鎖(Spinlock_t)航瞭,引用計(jì)數(shù)表(RefCountMap)滨彻,弱引用表(weak_table_t)。

SideTable 為什么是多張表,而不是一張表?:

如果只有一張表,如果想操作某一個(gè)對象的引用計(jì)數(shù),由于不同的對象是在不同的線程操作饮醇,由于不同線程需要來操作這張表祠墅,所以就有資源訪問的問題回铛,那么就需要對這張大表進(jìn)行加鎖操作,如果成千上萬對自己進(jìn)行引用計(jì)數(shù)操作巾乳,那么需要加鎖排隊(duì)压状,就會(huì)有效率問題碌廓,所以系統(tǒng)引用了 “分離鎖” 概念,比如 A玛臂,B同時(shí)進(jìn)行操作的話橱鹏,可以并發(fā)進(jìn)行杉辙,因?yàn)锳并淋,B唾琼,在不同的表中。

如果實(shí)現(xiàn)快速分流绞佩?找到當(dāng)前對象在哪張表中?:
SideTable 其實(shí)是一張 hash 表,key(對象指針)->hash函數(shù)->value(SideTable),通過這個(gè)hash計(jì)算之后咙好,就可以計(jì)算出當(dāng)前對象在哪個(gè)hash表中,也就找到了對應(yīng)的sideTable

hash 查找:

給定一個(gè)內(nèi)存地址抖苦,通過hash計(jì)算就可以得到數(shù)組的下標(biāo)地址,f(ptr) = ptr%arr.count商膊,比如內(nèi)存地址為1堤器,通過上面的就可以找到在數(shù)組中的位置

散列表的數(shù)據(jù)結(jié)構(gòu):

  • Spinlock_t:自旋鎖
    忙等乓旗,如果鎖已被其他線程獲取扰法,那么當(dāng)前線程會(huì)自己去不斷的獲取是否被釋放,直到其他線程釋放沸伏,適用于輕量訪問,如+1慧脱,-1染苛。

  • RefCountMap:引用計(jì)數(shù)表
    其實(shí)就是hash查找,提高查找效率呻此,插入和查找通過同一個(gè)hash函數(shù)來獲取贝乎,避免了循環(huán)遍歷。ptr->hash->size_t,其中的size_t就是引用計(jì)數(shù)值术裸,比如用64位存儲(chǔ)答倡,第一位表示(weakly_referenced),表示對象是否存在弱引用笨篷,下一位表示當(dāng)前對象是都正在dealloc(deallocating)辜贵,剩下的位表示引用計(jì)數(shù)值窟感。

  • weak_table_t:弱引用表
    也是一個(gè)hash表重荠,key->hash->weak_entry_t,weak_entry_t,其實(shí)是一個(gè)結(jié)構(gòu)體數(shù)組(weakPtr)罩扇,比如被weak修飾集侯,就存在這個(gè)弱引用表中泡挺。

3.ARC&MRC

4.引用計(jì)數(shù)

1. alloc出來引用計(jì)數(shù)

Person *p = [Person alloc]; // extrac = 0 
NSLog(@"%lu",(unsigned long)[p retainCount]); // 1媳溺,原理如下圖所示??
image.png

返回引用計(jì)數(shù)+1 所有打印的retainCount至少都是1

2.retain原理
執(zhí)行順序
<1> - (id)retain {}
<2> objc_object::rootRetain()參數(shù)分別:false,false
<3> objc_object::rootRetain(bool tryRetain, bool handleOverflow)
<4> 判斷新舊isa是否一致循環(huán)始藕,一致就執(zhí)行<9>扩借,否則執(zhí)行<5>
<5> 循環(huán)獲取舊值椒惨,并賦給新值,為新值進(jìn)行extra_rc+1
<6> 判斷是否溢出(x86_64 256)潮罪,沒溢出就執(zhí)行<9>康谆,溢出走<7>
<7> 執(zhí)行rootRetain_overflow领斥,回到<3>,handleOverflow為true沃暗,下次過來時(shí)執(zhí)行<8>
<8> x86_64留下引用計(jì)數(shù)的一半128月洛,復(fù)制另一半存進(jìn)去散列表
<9> return

// 并且調(diào)用retain的時(shí)候,傳入的兩個(gè)參數(shù)均為false
ALWAYS_INLINE id 
objc_object::rootRetain(bool tryRetain, bool handleOverflow)
{
    if (isTaggedPointer()) return (id)this;

    bool sideTableLocked = false;
    bool transcribeToSideTable = false;
    
    isa_t oldisa;
    isa_t newisa;

    
    // 循環(huán)條件:判斷是否獨(dú)一份存儲(chǔ)孽锥,對比新舊isa嚼黔,如果不是,就循環(huán)
    do {
        transcribeToSideTable = false;
        oldisa = LoadExclusive(&isa.bits);
        newisa = oldisa;
        if (slowpath(!newisa.nonpointer)) {
            ClearExclusive(&isa.bits);
            if (!tryRetain && sideTableLocked) sidetable_unlock();
            if (tryRetain) return sidetable_tryRetain() ? (id)this : nil;
            else return sidetable_retain();
        }
        // don't check newisa.fast_rr; we already called any RR overrides
        // 如果當(dāng)前對象的isa 正在銷毀
        if (slowpath(tryRetain && newisa.deallocating)) {
            ClearExclusive(&isa.bits);
            if (!tryRetain && sideTableLocked) sidetable_unlock();
            return nil;
        }
        //是否溢出惜辑,
        //經(jīng)過實(shí)驗(yàn):在x86_64架構(gòu)下,當(dāng)newisa.extra_rc為255時(shí)唬涧,在進(jìn)行addc,就會(huì)發(fā)生溢出
        //溢出之后盛撑,將會(huì)拿2的7次方的extra_rc 存到散列表中碎节,newisa.extra_rc回到128
        uintptr_t carry;
        //這里newisa.extra_rc 會(huì)+1 RC_ONE
        newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry);  // extra_rc++
        printf("%lu,",newisa.extra_rc);
        //newisa.extra_rc++如果溢出
        if (slowpath(carry)) {
            // newisa.extra_rc++ overflowed
            //第一次來的話,handleOverflow是false抵卫,會(huì)進(jìn)判斷語句
            if (!handleOverflow) {
                ClearExclusive(&isa.bits);
                //這里重新調(diào)用了當(dāng)前方法rootRetain钓株,但是handleOverflow = true
                return rootRetain_overflow(tryRetain);
            }
            // Leave half of the retain counts inline and 
            // prepare to copy the other half to the side table.
            // retry之后會(huì)來到這里
            // 翻譯:留下內(nèi)部關(guān)聯(lián)對象的一半,準(zhǔn)備復(fù)制另一半存進(jìn)去散列表
            if (!tryRetain && !sideTableLocked) {
                sidetable_lock();
            }
            sideTableLocked = true;
            transcribeToSideTable = true;
            newisa.extra_rc = RC_HALF;
            newisa.has_sidetable_rc = true;
        }
        //當(dāng)且僅當(dāng)舊值與存儲(chǔ)中的當(dāng)前值一致時(shí)陌僵,才把新值寫入存儲(chǔ)轴合。
    } while (slowpath(!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)));

    if (slowpath(transcribeToSideTable)) {
        // Copy the other half of the retain counts to the side table.
        // 拷貝一半(128)進(jìn)散列表
        sidetable_addExtraRC_nolock(RC_HALF);
    }

    if (slowpath(!tryRetain && sideTableLocked)) sidetable_unlock();
    return (id)this;
}

3.release
執(zhí)行順序
<1> - (oneway void)release {}
<2> objc_object::rootRelease() 參數(shù)分別:true,false
<3> objc_object::rootRelease(bool performDealloc, bool handleUnderflow)
<4> 判斷新舊isa是否一致循環(huán),一致就執(zhí)行return碗短,否則執(zhí)行<5>
<5> 循環(huán)獲取舊值受葛,并賦給新值,為新值進(jìn)行extra_rc-1
<6> 判斷是否溢出偎谁,沒溢出就執(zhí)行return总滩,溢出走<7> underflow
<7> 判斷是否有用到散列表
<8> 從散列表中拿出RC_HALF,將這部分存進(jìn)newisa
<9> 存成功就return巡雨,不成功就重試闰渔,再不行就把拿出來的放回去,然后goto retry;
<10> dealloc

ALWAYS_INLINE bool 
objc_object::rootRelease(bool performDealloc, bool handleUnderflow)
{
    if (isTaggedPointer()) return false;

    bool sideTableLocked = false;
    //新舊isa
    isa_t oldisa;
    isa_t newisa;

 retry:
    //跟retain一樣的判斷條件
    do {
        oldisa = LoadExclusive(&isa.bits);
        newisa = oldisa;
        if (slowpath(!newisa.nonpointer)) {
            ClearExclusive(&isa.bits);
            if (sideTableLocked) sidetable_unlock();
            return sidetable_release(performDealloc);
        }
        // don't check newisa.fast_rr; we already called any RR overrides
        uintptr_t carry;
        //newisa.extra_rc-1
        //如果溢出的時(shí)候铐望, newisa.extra_rc = 255
        newisa.bits = subc(newisa.bits, RC_ONE, 0, &carry);  // extra_rc--
        if (slowpath(carry)) {
            // don't ClearExclusive()
            //如果溢出走這
            printf("釋放溢出了,underflow\n");
            goto underflow;
        }
    } while (slowpath(!StoreReleaseExclusive(&isa.bits, 
                                             oldisa.bits, newisa.bits)));

    if (slowpath(sideTableLocked)) sidetable_unlock();
    return false;

 underflow:
    // newisa.extra_rc-- underflowed: borrow from side table or deallocate

    // abandon newisa to undo the decrement
    // 重新把舊isa給新isa冈涧,意思是把引用計(jì)數(shù)-1操作還原
    // 這時(shí)候的 newisa.extra_rc = 0
    newisa = oldisa;
    // retain的時(shí)候。如果有用到散列表正蛙,會(huì) newisa.has_sidetable_rc = true;
    if (slowpath(newisa.has_sidetable_rc)) {
        printf("發(fā)現(xiàn)has_sidetable_rc = true \n");
        // 調(diào)用release的時(shí)候handleUnderflow = false
        if (!handleUnderflow) {
            ClearExclusive(&isa.bits);
            //類似retain時(shí)候retry督弓,重新來一次,但是handleUnderflow為true
            return rootRelease_underflow(performDealloc);
        }

        // Transfer retain count from side table to inline storage.
        // 進(jìn)判斷前 sideTableLocked 沒有重新賦值乒验,所以一直是false
        if (!sideTableLocked) {
            ClearExclusive(&isa.bits);
            sidetable_lock();
            sideTableLocked = true;
            // Need to start over to avoid a race against 
            // the nonpointer -> raw pointer transition.
            // 去retry愚隧,重新回到上面,重復(fù)走一遍
            goto retry;
        }

        // Try to remove some retain counts from the side table.
        // 從散列表中拿出RC_HALF的引用計(jì)數(shù)
        size_t borrowed = sidetable_subExtraRC_nolock(RC_HALF);
        printf("借出來的 size === %lu \n",borrowed);
        // To avoid races, has_sidetable_rc must remain set 
        // even if the side table count is now zero.

        if (borrowed > 0) {
            // Side table retain count decreased.
            // Try to add them to the inline count.
            newisa.extra_rc = borrowed - 1;  // redo the original decrement too
            // 把拿出來的引用計(jì)數(shù)存到newisa
            bool stored = StoreReleaseExclusive(&isa.bits, 
                                                oldisa.bits, newisa.bits);
            if (!stored) {
                //如果沒存成功锻全,就換個(gè)姿勢再試試
                // Inline update failed. 
                // Try it again right now. This prevents livelock on LL/SC 
                // architectures where the side table access itself may have 
                // dropped the reservation.
                isa_t oldisa2 = LoadExclusive(&isa.bits);
                isa_t newisa2 = oldisa2;
                if (newisa2.nonpointer) {
                    uintptr_t overflow;
                    newisa2.bits = 
                        addc(newisa2.bits, RC_ONE * (borrowed-1), 0, &overflow);
                    if (!overflow) {
                        stored = StoreReleaseExclusive(&isa.bits, oldisa2.bits, 
                                                       newisa2.bits);
                    }
                }
            }

            if (!stored) {
                // 如果還是沒成功狂塘,把拿出來的放回去
                // Inline update failed.
                // Put the retains back in the side table.
                sidetable_addExtraRC_nolock(borrowed);
                goto retry;
            }

            // Decrement successful after borrowing from side table.
            // This decrement cannot be the deallocating decrement - the side 
            // table lock and has_sidetable_rc bit ensure that if everyone 
            // else tried to -release while we worked, the last one would block.
            sidetable_unlock();
            return false;
        }
        else {
            // Side table is empty after all. Fall-through to the dealloc path.
        }
    }

    // Really deallocate.
    // 如果newisa.has_sidetable_rc != true;
    // 就拋錯(cuò)录煤,release太多
    if (slowpath(newisa.deallocating)) {
        ClearExclusive(&isa.bits);
        if (sideTableLocked) sidetable_unlock();
        return overrelease_error();
        // does not actually return
    }
    newisa.deallocating = true;
    if (!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)) goto retry;

    if (slowpath(sideTableLocked)) sidetable_unlock();

    __sync_synchronize();
    if (performDealloc) {
        ((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc);
    }
    return true;
}

retain、release總結(jié)

現(xiàn)在isa是NONPOINTER_ISA,他是按位進(jìn)行存儲(chǔ)的荞胡,我們引用計(jì)數(shù)的存儲(chǔ)在2個(gè)位置妈踊,一個(gè)在extra_rc,第二個(gè)在散列表里面硝训。
retain:是會(huì)+1的 extra_rc + 1响委。extra_rc只有8個(gè)位置(X86下)當(dāng)超出的時(shí)候就會(huì)carry 也就是上溢出 就會(huì)把1半的空間往散列表里面丟,如果散列表里面都滿了那么這個(gè)時(shí)候會(huì)發(fā)生容量的變化窖梁。
relase: extra_rc -1 赘风,如果extra_rc為0的時(shí)候,在減1的時(shí)候就會(huì)是下溢出纵刘,首先會(huì)判斷散列表邀窃,如果散列表里面會(huì)借用一半的RC_HALF-1 存到extra_rc里面,如果散列表里面也沒有假哎,就會(huì)發(fā)生下溢出瞬捕,就觸發(fā)析構(gòu)函數(shù)。

  1. dealloc
    應(yīng)該做一些什么事情舵抹?

free函數(shù) - 釋放對象
weak弱引用計(jì)數(shù)表 - 處理
關(guān)聯(lián)對象 associated

5.弱引用

不操作引用計(jì)數(shù)

散列表里面有weak 對象
1:weak_register_no_lock
2:從我們的散列表的 weak_table 哈希表—>weak_entry_t *entry;
3: weak_entry_t *weak_entries 下標(biāo) 下的 entry
4:entry->inline_referrers[i] = new_referrer;
5:new_referrers[i] = entry->inline_referrers[i]
6:entry->referrers = new_referrers;

總結(jié)

sidetabels — sidetable - 弱引用表
weakTable - entry - 數(shù)組 - 弱引用對象指針
更詳細(xì)的解析

6.自動(dòng)釋放池

什么時(shí)候用到

自動(dòng)釋放池 : 容納變量 - 釋放
1:大量的臨時(shí)變量
2:非UI操作, 命令行
3:自己創(chuàng)建輔助線程

原理

__AtAutoreleasePool __autoreleasepool;
objc_autoreleasePoolPush --> atautoreleasepoolobj
objc_autoreleasePoolPop

AutoreleasePoolPage::push();
page:屬性 56個(gè)字節(jié)
一頁所能容乃的大小: 4096
// 505 滿
// 38 = 3*16+8 = 48+8 = 56
// 16進(jìn)制 8
// 0x103803038 邊界 -- 加進(jìn)去 壓棧 -- 剪出來 出棧 - 頁面銷毀
自動(dòng)釋放池 - 雙向鏈表
這一頁是不是滿 --
4096 - 屬性 56 push 壓棧 + 邊界符 - 開辟新的頁面 壓棧

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肪虎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子惧蛹,更是在濱河造成了極大的恐慌扇救,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件香嗓,死亡現(xiàn)場離奇詭異迅腔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)靠娱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門沧烈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人像云,你說我怎么就攤上這事锌雀。” “怎么了苫费?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵汤锨,是天一觀的道長。 經(jīng)常有香客問我百框,道長,這世上最難降的妖魔是什么牍汹? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任铐维,我火速辦了婚禮柬泽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嫁蛇。我一直安慰自己锨并,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布睬棚。 她就那樣靜靜地躺著第煮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抑党。 梳的紋絲不亂的頭發(fā)上包警,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音底靠,去河邊找鬼害晦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛暑中,可吹牛的內(nèi)容都是我干的壹瘟。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼鳄逾,長吁一口氣:“原來是場噩夢啊……” “哼稻轨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起雕凹,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對情侶失蹤殴俱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后请琳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粱挡,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年俄精,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了询筏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡竖慧,死狀恐怖嫌套,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情圾旨,我是刑警寧澤踱讨,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站砍的,受9級(jí)特大地震影響痹筛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一帚稠、第九天 我趴在偏房一處隱蔽的房頂上張望谣旁。 院中可真熱鬧,春花似錦滋早、人聲如沸榄审。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搁进。三九已至,卻和暖如春昔头,著一層夾襖步出監(jiān)牢的瞬間饼问,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國打工减细, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匆瓜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓未蝌,卻偏偏與公主長得像驮吱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子萧吠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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