iOS retainCount存放位置 & weak置nil

參考文章
iOS引用計(jì)數(shù)管理之揭秘計(jì)數(shù)存儲(chǔ)
OC源碼 —— retain和release

文章目錄
參考文章
tips
一、TaggedPointer和Non-pointer
1.1.TaggedPointer
1.1.1. taggedPointer數(shù)據(jù)在內(nèi)存中的地址
1.1.2. 一些別的
1.1.3. 臨界值測(cè)試——taggedPointer的存儲(chǔ)形式
1.2. 優(yōu)化的isa——Non-poniter
1.3. 是否開(kāi)啟non-pointer時(shí)isa的賦值
二、進(jìn)入正題
2.1.Tagged Pointer對(duì)象
2.2. 開(kāi)啟了Non-pointer的isa
2.2.1. retain
源碼
不溢出
一些提到的方法
實(shí)現(xiàn)功能
溢出
用到的方法
實(shí)現(xiàn)功能
由源碼可知實(shí)現(xiàn)原理
2.2.2. release
2.3 未開(kāi)啟Non-pointer isa
總結(jié)
weak置nil
注釋部分

tips

  • 如果對(duì)象不是Tagged Pointer且關(guān)閉了Non-pointer拧篮,那該對(duì)象的引用計(jì)數(shù)就使用SideTable來(lái)存荠呐。
  • isa中存放retainConut楞艾,存放在uintptr_t extra_rc辉川,(“uintptr_t:一個(gè)能夠存儲(chǔ)指針的無(wú)符號(hào)int芦岂。這通常意味著它與指針的大小相同”)(最后的注釋部分是我搜到的 沒(méi)咋看明白)。最大值為2^8-1宠哄,也就是255壹将,也就是8位二進(jìn)制碼全是1時(shí)的情況,所以應(yīng)該是占一字節(jié)毛嫉。
  • 當(dāng)isa中存放滿(mǎn)了時(shí)诽俯,就分一半到sideTable,isa中繼續(xù)存承粤,再次存滿(mǎn)后暴区,又分一半給sidetable。
  • extra_rc存放的是引用計(jì)數(shù)的值減1

一辛臊、TaggedPointer和Non-pointer

1.1.TaggedPointer

1.Tagged Pointer專(zhuān)門(mén)用來(lái)存儲(chǔ)小的對(duì)象仙粱,例如NSNumber和NSDate 2:Tagged
2.Pointer指針的值不再是地址了,而是真正的值彻舰。所以伐割,實(shí)際上它不再是一個(gè)對(duì)象了,它只是一個(gè)披著對(duì)象皮的普通變量而已淹遵。所以口猜,它的內(nèi)存并不存儲(chǔ)在堆中,也不需要malloc和free透揣。
3.在內(nèi)存讀取上有著3倍的效率济炎,創(chuàng)建時(shí)比以前快106倍。

目前我所知的系統(tǒng)中可以啟用Tagged Pointer的類(lèi)對(duì)象有:NSDate辐真、NSNumber须尚、NSString。

1.1.1. taggedPointer數(shù)據(jù)在內(nèi)存中的地址
NSLog(@"%p",@(@(1).intValue));//0x127
NSLog(@"%p",@(@(2).intValue));//0x227

由此可知int類(lèi)型的tag為27侍咱,因?yàn)槿サ?7后0x1 = 1耐床,0x2 = 2,正好是值楔脯。所以@(1)撩轰、@(2)也不是一個(gè)對(duì)象,只是一個(gè)普通變量昧廷。

1.1.2. 一些別的
int 17:10001堪嫂,5位;
long long 37:100101木柬,6位皆串;
double 57:111001,6位眉枕。
…
1.1.3. 臨界值測(cè)試——taggedPointer的存儲(chǔ)形式

有以下測(cè)試可知恶复,double數(shù)據(jù)型的taggedPointer臨界值為@(pow(2, 55) - 3)

NSLog(@"%p",@(pow(2, 55) - 3));//0x7ffffffffffffc57

NSLog(@"%p",@(pow(2, 55) - 2));//0x6030002c50c0

*(不太理解為什么是-3怜森,我感覺(jué)應(yīng)該是-1,這樣他表示的最大值就是符合常理的數(shù)據(jù)位全是1)
2的55次方-3谤牡,結(jié)果為55位二進(jìn)制碼副硅,符號(hào)位占一位,就是56位拓哟,也就是7字節(jié)想许,而double數(shù)據(jù)存儲(chǔ)在內(nèi)存中就是8字節(jié)伶授,所以我們推測(cè)断序,tag值應(yīng)該占一字節(jié),也就是8位糜烹。

  • 這個(gè)單純就是一個(gè)地址了违诗,沒(méi)有57這個(gè)tag了,里面并沒(méi)有存值的內(nèi)容疮蹦,所以Tagged Pointer失效了诸迟。
1.2. 優(yōu)化的isa——Non-poniter

舊版的isa

typedef struct objc_object *id
struct objc_object {
    Class _Nonnull isa;
}

目前的isa

struct objc_object {
private:
    isa_t isa;
  ...
}
isa_t isa = {
    Class class = Person;
    uintptr_t bits = 8303516107940673;
    struct {
        uintptr_t nonpointer = 1;
        uintptr_t has_assoc  = 0;
        uintptr_t has_cxx_dtor = 0;
        uintptr_t shiftcls = 536872040; 
        uintptr_t magic = 59;
        uintptr_t weakly_referenced = 0;
        uintptr_t deallocating = 0;
        uintptr_t has_sidetable_rc = 0;
        uintptr_t extra_rc = 0;
    }
}

參數(shù)介紹:

1.nonpointer
0,代表普通的指針愕乎,存儲(chǔ)著Class阵苇、Meta-Class對(duì)象的內(nèi)存地址
1,代表優(yōu)化過(guò)感论,使用位域存儲(chǔ)更多的信息

2.has_assoc
是否有設(shè)置過(guò)關(guān)聯(lián)對(duì)象绅项,如果沒(méi)有,釋放時(shí)會(huì)更快

3.has_cxx_dtor
是否有C++的析構(gòu)函數(shù)(.cxx_destruct)比肄,如果沒(méi)有快耿,釋放時(shí)會(huì)更快

4.shiftcls
存儲(chǔ)著Class、Meta-Class對(duì)象的內(nèi)存地址信息

5.magic
用于在調(diào)試時(shí)分辨對(duì)象是否未完成初始化

6.weakly_referenced
是否有被弱引用指向過(guò)芳绩,如果沒(méi)有掀亥,釋放時(shí)會(huì)更快

7.deallocating
對(duì)象是否正在釋放

8.extra_rc
里面存儲(chǔ)的值是引用計(jì)數(shù)器減1

9.has_sidetable_rc
引用計(jì)數(shù)器是否過(guò)大無(wú)法存儲(chǔ)在isa中
如果為1,那么引用計(jì)數(shù)會(huì)存儲(chǔ)在一個(gè)叫SideTable的類(lèi)的屬性中

不使用non-pointer的isa可以簡(jiǎn)化為

isa_t isa = {
    Class class = Person;
}

1.3. 是否開(kāi)啟non-pointer時(shí)isa的賦值

objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) { 
    if (!nonpointer) {
        isa.cls = cls;
    } else {
        isa_t newisa(0);
        ......
        (成員賦值)
        ......
        isa = newisa;
    }
}

二妥色、進(jìn)入正題

按以下順序搪花,滿(mǎn)足1則不判斷2,依次類(lèi)推嘹害。

1:對(duì)象是否是Tagged Pointer對(duì)象撮竿;
2:對(duì)象是否啟用了Non-pointer;
3:對(duì)象未啟用Non-pointer吼拥。

2.1.Tagged Pointer對(duì)象

先說(shuō)結(jié)論:對(duì)于Tagged Pointer對(duì)象倚聚,并沒(méi)有任何的引用計(jì)數(shù)操作,引用計(jì)數(shù)數(shù)量也只是單純的返回自己地址罷了凿可。
retain時(shí)惑折。

id objc_object::rootRetain(bool tryRetain, bool handleOverflow) {
    if (isTaggedPointer()) return (id)this;
    ...
}

release時(shí)授账。

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

retainCount時(shí)。

uintptr_t objc_object::rootRetainCount() {
    if (isTaggedPointer()) return (uintptr_t)this;
    ...
}

2.2. 開(kāi)啟了Non-pointer的isa

這里寫(xiě)的簡(jiǎn)單惨驶,上面部分寫(xiě)的詳細(xì)一點(diǎn)白热。
如果對(duì)象開(kāi)啟了Non-pointer,那么引用計(jì)數(shù)是存在isa中的粗卜,引用計(jì)數(shù)超過(guò)255將附加SideTable輔助存儲(chǔ)屋确。

OC源碼 —— retain和release

2.2.1. retain

源碼

[NSObject retain];

- (id)retain {
    return ((id)self)->rootRetain();
}

id objc_object::rootRetain()
{
    return rootRetain(false, false);
}

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;

    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();
        }
        if (slowpath(tryRetain && newisa.deallocating)) {
            ClearExclusive(&isa.bits);
            if (!tryRetain && sideTableLocked) sidetable_unlock();
            return nil;
        }
        uintptr_t carry;
        newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry); 

        if (slowpath(carry)) {
            if (!handleOverflow) {
                ClearExclusive(&isa.bits);
                return rootRetain_overflow(tryRetain);
            }
            if (!tryRetain && !sideTableLocked) sidetable_lock();
            sideTableLocked = true;
            transcribeToSideTable = true;
            newisa.extra_rc = RC_HALF;
            newisa.has_sidetable_rc = true;
        }
    } while (slowpath(!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)));

    if (slowpath(transcribeToSideTable)) {
        sidetable_addExtraRC_nolock(RC_HALF);
    }

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

源碼中carry的意思是溢出,溢出也就是isa中存不下了续扔,isa中的參數(shù)uintptr_t has_sidetable_rc : 1攻臀。

不溢出
首先我們看不溢出的情況

id 
objc_object::rootRetain(bool tryRetain, bool handleOverflow)
{
    isa_t oldisa;
    isa_t newisa;

    do {
        oldisa = LoadExclusive(&isa.bits);  //獲取isa的bit信息,也就是isa中的內(nèi)容
        newisa = oldisa;
        uintptr_t carry;
        newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry); 
    } while (slowpath(!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)));

    return (id)this;
}

一些提到的方法
1.LoadExclusive: 用于返回isa的內(nèi)容

LoadExclusive(&isa.bits)

static uintptr_t LoadExclusive(uintptr_t *src)
{
    return *src;
}

2.addc

addc(newisa.bits, RC_ONE, 0, &carry)
#       define RC_ONE   (1ULL<<56)

static uintptr_t addc(uintptr_t lhs, uintptr_t rhs, uintptr_t carryin, uintptr_t *carryout)
{
    return __builtin_addcl(lhs, rhs, carryin, carryout);
}

這個(gè)方法沒(méi)搜到纱昧,官方不對(duì)外公開(kāi)刨啸,根據(jù)OC源碼 —— retain和release測(cè)試

實(shí)現(xiàn)功能
其實(shí)就是給extra_rc+1,然后更新一下isa的內(nèi)容识脆。

溢出

id objc_object::rootRetain(bool tryRetain, bool handleOverflow)
{
   isa_t oldisa;
   isa_t newisa;

   oldisa = LoadExclusive(&isa.bits);
   newisa = oldisa;
   uintptr_t carry;
   newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry); 
   
   if (!handleOverflow) {
       ClearExclusive(&isa.bits);
       return rootRetain_overflow(tryRetain);    //內(nèi)部是調(diào)用了rootretain设联,知識(shí)第二個(gè)參數(shù)由true變?yōu)閒alse。
   }
}

通過(guò)rootRetain_overflow內(nèi)部是調(diào)用了rootretain灼捂,知識(shí)第二個(gè)參數(shù)由true變?yōu)閒alse离例。所以實(shí)際源碼是

id objc_object::rootRetain(bool tryRetain, bool handleOverflow)
{
    isa_t oldisa;
    isa_t newisa;

    do {
        oldisa = LoadExclusive(&isa.bits);
        newisa = oldisa;
        uintptr_t carry;
        newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry);

        newisa.extra_rc = RC_HALF;
        newisa.has_sidetable_rc = true;
    } while (slowpath(!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)));

    sidetable_addExtraRC_nolock(RC_HALF);

    return (id)this;
}
#       define RC_HALF  (1ULL<<7)

用到的方法
rootRetain_overflow():內(nèi)部是調(diào)用了rootretain,知識(shí)第二個(gè)參數(shù)由true變?yōu)閒alse悉稠。

id objc_object::rootRetain_overflow(bool tryRetain)
{
    return rootRetain(tryRetain, true);
}

sidetable_addExtraRC_nolock: 溢出后宫蛆,溢出除了存放在isa中的值變?yōu)橐话耄O轮档奶幚怼?/p>

sidetable_addExtraRC_nolock(RC_HALF);

bool objc_object::sidetable_addExtraRC_nolock(size_t delta_rc)
{
    SideTable& table = SideTables()[this];

    size_t& refcntStorage = table.refcnts[this];
    size_t oldRefcnt = refcntStorage;
    // isa-side bits should not be set here
    assert((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
    assert((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);

    if (oldRefcnt & SIDE_TABLE_RC_PINNED) return true;

    uintptr_t carry;
    size_t newRefcnt = addc(oldRefcnt, delta_rc << SIDE_TABLE_RC_SHIFT, 0, &carry);
    if (carry) {
        refcntStorage = SIDE_TABLE_RC_PINNED | (oldRefcnt & SIDE_TABLE_FLAG_MASK);
        return true;
    }
    else {
        refcntStorage = newRefcnt;
        return false;
    }
}

#define SIDE_TABLE_WEAKLY_REFERENCED (1UL<<0)
#define SIDE_TABLE_DEALLOCATING      (1UL<<1)  
#define SIDE_TABLE_RC_ONE            (1UL<<2)
#define SIDE_TABLE_RC_SHIFT 2

實(shí)現(xiàn)功能
更新了newisa的extra_rc和has_sidetable_rc字段偎球,將extra_rc設(shè)置為了RC_HALF也就是128洒扎,has_sidetable_rc設(shè)為true,將一半的引用計(jì)數(shù)存放到SideTable中衰絮。當(dāng)isa再次溢出時(shí)袍冷,addc之后又加了128進(jìn)去。說(shuō)白了每次extra_rc溢出了猫牡,SideTable中就增加128胡诗。

由源碼可知實(shí)現(xiàn)原理
isa的extra_rc用來(lái)存放引用計(jì)數(shù)值,has_sidetable_rc用來(lái)表示有無(wú)用sideTable存引用計(jì)數(shù)淌友。
當(dāng)isa中的extra_rc值小于等于255時(shí)煌恢,存放在extra_rc中,此時(shí)has_sidetable_rc值為0震庭,而超過(guò)這個(gè)值后瑰抵,超過(guò)的那一刻has_sidetable_rc的值變?yōu)?,把isa的extra_rc中的值分一半給sidetable器联,然后繼續(xù)往isa中存二汛,再次存滿(mǎn)時(shí)婿崭,就再往sidetable中分一半。也就是說(shuō)每次isa的extra_rc存滿(mǎn)肴颊,就變成128氓栈,剩下的加到sidetable中。

2.2.2. release

在深入理解了retain之后婿着,再看release的源碼就很簡(jiǎn)單了授瘦。代碼太長(zhǎng)我就不貼了,總結(jié)一下release的流程:

  • 最普通的情況竟宋,直接將extra_rc減1
  • 如果extra_rc為0提完,判斷has_sidetable_rc
  • has_sidetable_rc = false,說(shuō)明對(duì)象已經(jīng)沒(méi)有引用計(jì)數(shù)了袜硫,直接dealloc釋放內(nèi)存
  • has_sidetable_rc = true氯葬,說(shuō)明extra_rc有過(guò)溢出
  • 從SideTable中借位成功挡篓,每次取RC_HALF婉陷,也就是128,減1之后賦給extra_rc官研,回到步驟1
  • 從SideTable中借位失敗秽澳,直接dealloc

2.3 未開(kāi)啟Non-pointer isa

存到sideTable中,這部分源碼詳見(jiàn)iOS引用計(jì)數(shù)管理之揭秘計(jì)數(shù)存儲(chǔ)

總結(jié)

這片博客講的是引用計(jì)數(shù)的存放位置戏羽,做以下總結(jié):
針對(duì)數(shù)據(jù)分為三種:TaggedPointer對(duì)象担神,未開(kāi)啟non-pointer的isa對(duì)象,開(kāi)啟non-pointer的isa對(duì)象始花。

1.TaggedPointe對(duì)象妄讯,retainCount返回自己本身,也就是說(shuō)酷宵,對(duì)于Tagged Pointer對(duì)象亥贸,并沒(méi)有任何的引用計(jì)數(shù)操作,引用計(jì)數(shù)數(shù)量也只是單純的返回自己地址罷了浇垦。
2.開(kāi)啟了non-pointer的isa:先存放在isa的extra_rc中炕置,存滿(mǎn)之后,isa的 has_sidetable_rc值由0變?yōu)?男韧,分一半到sideTable中朴摊,然后繼續(xù)往isa的extra_rc中,存滿(mǎn)之后繼續(xù)分一半此虑。如果sideTable中也存滿(mǎn)了甚纲,sideTable的RefCountMap的pinned由0變?yōu)?,表示不能再增加了朦前。
3.未開(kāi)啟non-pointer的isa介杆,存放在sideTable中讹弯。

weak置nil

runtime維護(hù)著一個(gè)weak表即hash表,用于存儲(chǔ)指向?qū)ο蟮膚eak指針
Weak表是Hash表这溅,Key是所指對(duì)象的地址组民,Value是Weak指針地址的數(shù)組
以對(duì)象的地址作為key,去找weak指針
觸發(fā)調(diào)用arr_clear_deallocating 函數(shù) 悲靴,根據(jù)對(duì)象的地址將所有weak指針地址的數(shù)組臭胜,遍歷數(shù)組把其中的數(shù)據(jù)置為nil。

注釋部分

什么是uintptr_t數(shù)據(jù)類(lèi)型癞尚?
uintptr_t extra_rc = 0;(8位耸三,所以最多存到255,到256時(shí)要存到別的地方)

第一件事浇揩,在問(wèn)題提出的時(shí)候仪壮,uintptr_t不在C++中。在C99中<stdint.h>胳徽,作為可選類(lèi)型积锅。許多C++03編譯器
確實(shí)提供了該文件。它也在C++11中养盗,在缚陷,這里它還是可選的,它引用C99作為定義往核。

在C99中箫爷,它被定義為“一個(gè)無(wú)符號(hào)整數(shù)類(lèi)型,它的屬性是聂儒,任何指向void的有效指針都可以轉(zhuǎn)換為此類(lèi)型虎锚,然后再轉(zhuǎn)換回指針為void,結(jié)果將與原始指針相比較”衩婚。

把這個(gè)當(dāng)成它說(shuō)的意思窜护。它沒(méi)有提到任何關(guān)于尺寸的東西。

uintptr_t可能與void它可能更大谅猾。盡管這樣的C++實(shí)現(xiàn)方法是不正常的柄慰,但它可能會(huì)更小。例如税娜,在某個(gè)假設(shè)的平臺(tái)上void是32位坐搔,但是只使用了24位虛擬地址空間,您可以擁有24位敬矩。uintptr_t滿(mǎn)足了要求概行。我不知道為什么一個(gè)實(shí)現(xiàn)會(huì)這樣做,但標(biāo)準(zhǔn)允許這樣做弧岳。

它是一個(gè)能夠存儲(chǔ)指針的無(wú)符號(hào)int凳忙。這通常意味著它與指針的大小相同业踏。它是在C++11和更高版本的標(biāo)準(zhǔn)中定義的。

想要一個(gè)能夠保存架構(gòu)指針類(lèi)型的整數(shù)類(lèi)型的一個(gè)常見(jiàn)原因是對(duì)指針執(zhí)行特定于整數(shù)的操作涧卵,或者通過(guò)提供一個(gè)整數(shù)“句柄”來(lái)模糊指針的類(lèi)型勤家。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市柳恐,隨后出現(xiàn)的幾起案子伐脖,更是在濱河造成了極大的恐慌,老刑警劉巖乐设,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讼庇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡近尚,警方通過(guò)查閱死者的電腦和手機(jī)蠕啄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)戈锻,“玉大人歼跟,你說(shuō)我怎么就攤上這事〔芭妫” “怎么了嘹承?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)如庭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)撼港,這世上最難降的妖魔是什么坪它? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮帝牡,結(jié)果婚禮上往毡,老公的妹妹穿的比我還像新娘。我一直安慰自己靶溜,他們只是感情好开瞭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著罩息,像睡著了一般嗤详。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瓷炮,一...
    開(kāi)封第一講書(shū)人閱讀 51,718評(píng)論 1 305
  • 那天葱色,我揣著相機(jī)與錄音,去河邊找鬼娘香。 笑死苍狰,一個(gè)胖子當(dāng)著我的面吹牛办龄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播淋昭,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼俐填,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了翔忽?” 一聲冷哼從身側(cè)響起玷禽,我...
    開(kāi)封第一講書(shū)人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呀打,沒(méi)想到半個(gè)月后矢赁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贬丛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年撩银,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豺憔。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡额获,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恭应,到底是詐尸還是另有隱情抄邀,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布昼榛,位于F島的核電站境肾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏胆屿。R本人自食惡果不足惜奥喻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望非迹。 院中可真熱鬧环鲤,春花似錦、人聲如沸憎兽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纯命。三九已至西剥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扎附,已是汗流浹背蔫耽。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人匙铡。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓图甜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親鳖眼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子黑毅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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