帶有問(wèn)題看原始文件----子線程AutoRelease對(duì)象何時(shí)釋放

首先是一個(gè)常規(guī)問(wèn)題色迂,autorelease對(duì)象何時(shí)釋放香缺?答:在AutoreleasePoolPage pop的時(shí)候釋放,在主線程的runloop中歇僧,有兩個(gè)oberserver負(fù)責(zé)創(chuàng)建和清空autoreleasepool图张,詳情可以看YY的深入理解runloop。那么子線程呢诈悍?子線程的runloop都需要手動(dòng)開(kāi)啟祸轮,那么子線程中使用autorelease對(duì)象會(huì)內(nèi)存泄漏嗎,如果不會(huì)又是什么時(shí)候釋放呢侥钳。

Runloop原始碼

帶著這個(gè)問(wèn)題适袜,我們看一看runloop的原始碼中答案的答案。

autoreleasepool

在MRC下舷夺,使用__autoreleasing修飾符等同于MRC下調(diào)用自動(dòng)發(fā)布方法苦酱,所以在NSObject子系統(tǒng)中找到-(id)autorelese方法開(kāi)始看售貌。

1

2

3

4

-(id)autorelease

{

? ? return _objc_rootAutorelease(self);

}

可以看到這個(gè)方法里只是簡(jiǎn)單的調(diào)了一下_objc_rootAutorelease(),繼續(xù)跟進(jìn)疫萤。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

id

_objc_rootAutorelease(id obj)

{

? ? assert(obj);

? ? 返回obj-> rootAutorelease();

}

...

//基本自動(dòng)發(fā)布實(shí)現(xiàn)趁矾,忽略替代拐迁。

內(nèi)聯(lián)ID

objc_object :: rootAutorelease()

{

? ? 如果(isTaggedPointer())返回(id)

? ? 如果(prepareOptimizedReturn(ReturnAtPlus1))返回(id)

? ? 返回rootAutorelease2();

}

...

__attribute __((noinline定硝,used))

id

objc_object :: rootAutorelease2()

{

? ? assert(滓玖!isTaggedPointer());

? ? 返回AutoreleasePoolPage :: autorelease((id)this);

}

檢查是否AutoreleasePoolPage :: autorelease是標(biāo)簽指針和是否要做不加入autoreleasepool的優(yōu)化,然后rootAutorelease2()帝际。最后走入了AutoreleasePoolPage::autorelease()。

接下來(lái)看看AutoreleasePoolPage這個(gè)類饶辙,有關(guān)這個(gè)類的說(shuō)明蹲诀,可以看看sunny的黑幕背后的Autorelease。現(xiàn)在來(lái)看看AutoreleasePoolPage中的實(shí)現(xiàn)弃揽。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

public:

? ? 靜態(tài)內(nèi)聯(lián)ID autorelease(id obj)

? ? {

? ? ? ? assert(obj);

? ? ? ? assert(脯爪!obj-> isTaggedPointer());

? ? ? ? id * dest __unused = autoreleaseFast(obj);

? ? ? ? assert(!dest || dest == EMPTY_POOL_PLACEHOLDER || * dest == obj);

? ? ? ? 返回obj;

? ? }

? ? ...

? ? 靜態(tài)內(nèi)聯(lián)ID * autoreleaseFast(id obj)

? ? {

? ? ? ? AutoreleasePoolPage * page = hotPage();

? ? ? ? if(page &&矿微!page-> full()){

? ? ? ? ? ? 返回頁(yè)面-> add(obj);

? ? ? ? } else if(page){

? ? ? ? ? ? 返回autoreleaseFullPage(obj痕慢,page);

? ? ? ? } else {

? ? ? ? ? ? return autoreleaseNoPage(obj);

? ? ? ? }

? ? }

? ? ...

? ? ? ? 靜態(tài)__attribute __((noinline))

? ? id * autoreleaseNoPage(id obj)

? ? {

? ? ? ? //“無(wú)頁(yè)面”可能意味著沒(méi)有推送池

? ? ? ? //或推送了一個(gè)空的占位符池且尚無(wú)內(nèi)容

? ? ? ? assert(!hotPage ())涌矢;

? ? ? ? bool pushExtraBoundary = false;

? ? ? ? if(haveEmptyPoolPlaceholder()){

? ? ? ? ? ? //我們將第二個(gè)池推入空的占位符池

? ? ? ? ? ? //或?qū)⒌谝粋€(gè)對(duì)象推入空的占位符池掖举。

? ? ? ? ? ? //在此之前,代表

? ? ? ? ? ? 當(dāng)前由空占位符表示的池// 推入池邊界娜庇。

? ? ? ? ? ? pushExtraBoundary = true;

? ? ? ? }

? ? ? ? 否則if(obj塔次!= POOL_BOUNDARY && DebugMissingPools){

? ? ? ? ? ? //我們正在推送一個(gè)沒(méi)有池的對(duì)象,

? ? ? ? ? ? //環(huán)境請(qǐng)求了無(wú)池調(diào)試名秀。

? ? ? ? ? ? _objc_inform(“ MISSING POOLS:(%p)類%s的對(duì)象%p”

? ? ? ? ? ? ? ? ? ? ? ? “自動(dòng)釋放励负,沒(méi)有池-”

? ? ? ? ? ? ? ? ? ? ? ? “只是泄漏-中斷”

? ? ? ? ? ? ? ? ? ? ? ? “要調(diào)試的objc_autoreleaseNoPool()”,

? ? ? ? ? ? ? ? ? ? ? ? pthread_self()匕得,(void *)obj继榆,object_getClassName(obj));

? ? ? ? ? ? objc_autoreleaseNoPool(obj);

? ? ? ? ? ? 返回零耗跛;

? ? ? ? }

? ? ? ? 否則裕照,如果(obj == POOL_BOUNDARY &&!DebugPoolAllocation){

? ? ? ? ? ? //我們?cè)跊](méi)有池的情況下推送一個(gè)池调塌,

? ? ? ? ? ? //并且不請(qǐng)求每個(gè)池分配調(diào)試晋南。

? ? ? ? ? ? //安裝并返回空池占位符。

? ? ? ? ? ? 返回setEmptyPoolPlaceholder();

? ? ? ? }

? ? ? ? //我們正在推送對(duì)象或非占位符的池羔砾。

? ? ? ? //安裝首頁(yè)负间。

? ? ? ? AutoreleasePoolPage * page =新的AutoreleasePoolPage(nil);

? ? ? ? setHotPage(page);? ? ? ? //代表先前占位符的池推邊界偶妖。? ? ? ? 如果(pushExtraBoundary){? ? ? ? ? ? page-> add(POOL_BOUNDARY);? ? ? ? }? ? ? ? //推送請(qǐng)求的對(duì)象或池。? ? ? ? 返回頁(yè)面->添加(obj);? ? }



這里我們找到了我們想看的代碼政溃,如果當(dāng)前線程沒(méi)有AutorelesepoolPage的話趾访,代碼執(zhí)行順序?yàn)閍utorelease-> autoreleaseFast-> autoreleaseNoPage。

在autoreleaseNoPage方法中董虱,會(huì)創(chuàng)建一個(gè)hotPage扼鞋,然后調(diào)用page-> add(obj)。也就是說(shuō)甚至這個(gè)線程沒(méi)有AutorelesepoolPage愤诱,使用了autorelease對(duì)象時(shí)也會(huì)new一個(gè)AutoreleasepoolPage出來(lái)管理autorelese對(duì)象云头,不用擔(dān)心內(nèi)存泄漏。

何時(shí)釋放

明確了何時(shí)創(chuàng)建autoreleasepool之后就自然而然的有下一個(gè)問(wèn)題淫半,這個(gè)autoreleasepool何時(shí)清空溃槐?

對(duì)于這個(gè)問(wèn)題,這里使用watchpoint set variable命令來(lái)觀察科吭。

首先是一個(gè)最簡(jiǎn)單的場(chǎng)景昏滴,創(chuàng)建一個(gè)子線程。

1

2

3

4

__weak id obj;

...

[NSThread detachNewThreadSelector:@selector(createAndConfigObserverInSecondaryThread)toTarget:self withObject:nil];

使用一個(gè)弱指針觀察子線程中的自動(dòng)釋放對(duì)象对人,子線程中執(zhí)行的任務(wù)谣殊。

1

2

3

4

5

6

7

-(void)createAndConfigObserverInSecondaryThread {

? ? __autoreleasing id test = [NSObject new];

? ? NSLog(@“ obj =%@”,測(cè)試);

? ? obj =測(cè)試牺弄;

? ? [[NSThread currentThread] setName:@“ test runloop thread”]蟹倾;

? ? NSLog(@“線程結(jié)束”);

}

在該obj =測(cè)試位置設(shè)置斷點(diǎn)使用watchpoint set variable obj命令觀察obj,可以看到obj在釋放時(shí)的方法調(diào)用棧是這樣的猖闪。通過(guò)這個(gè)調(diào)用椣侍模可以看到釋放的時(shí)機(jī)在_pthread_exit。這個(gè)方法如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

靜態(tài)無(wú)效tls_dealloc(void * p)

{

? ? if(p ==(void *)EMPTY_POOL_PLACEHOLDER){

? ? ? ? //這里沒(méi)有要清理的對(duì)象或池頁(yè)面培慌。

? ? ? ? 返回;

? ? }

? ? //恢復(fù)工作時(shí)的TLS值

? ? setHotPage((AutoreleasePoolPage *)p);

? ? 如果(AutoreleasePoolPage * page = coldPage()){

? ? ? ? if(豁陆!page-> empty())pop(page-> begin()); //

? ? ? ? 如果(DebugMissingPools || DebugPoolAllocation){

? ? ? ? ? ? // pop()已殺死所有頁(yè)面,則彈出所有池

? ? ? ? } else {

? ? ? ? ? ? page-> kill(); //釋放所有頁(yè)面

? ? ? ? }

? ? }? ? //清除TLS值吵护,以便TLS銷毀不會(huì)循環(huán)? ? setHotPage(nil); }


在這找到了if (!page->empty()) pop(page->begin());這句關(guān)鍵代碼盒音。再往上看一點(diǎn),在_pthread_exit時(shí)會(huì)執(zhí)行下面這個(gè)函數(shù)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

void

_pthread_tsd_cleanup(pthread_t self)

{

#if馅而!VARIANT_DYLD

int j;

//首先

為(j = 0; j <PTHREAD_DESTRUCTOR_ITERATIONS; j ++)清理動(dòng)態(tài)鍵{

pthread_key_t k;

for(k = __pthread_tsd_start; k <= self-> max_tsd_key; k ++){_

pthread_tsd_cleanup_key(self祥诽,k);

}

}

self-> max_tsd_key = 0;

//清理

(j = 0; j <PTHREAD_DESTRUCTOR_ITERATIONS; j ++)的靜態(tài)鍵{

pthread_key_t k;

for(k = __pthread_tsd_first; k <=

__pthread_tsd_max ; k ++){_ pthread_tsd_cleanup_key(self,k);

}

}

#endif //瓮恭!VARIANT_DYLD

}

該線程在退出時(shí)會(huì)釋放自身資源雄坪,這個(gè)操作就包含了銷毀自動(dòng)釋放池,在tls_delloc中屯蹦,執(zhí)行了pop操作维哈。

這個(gè)實(shí)驗(yàn)本該到此就結(jié)束了绳姨,對(duì)于文章開(kāi)始的問(wèn)題在這里也已經(jīng)有了答案,線程在銷毀時(shí)會(huì)清空autoreleasepool阔挠。但是上述這個(gè)示例中的線程并沒(méi)有加入runloop飘庄,只是一個(gè)一次性的線程。現(xiàn)在給這個(gè)線程加入runloop來(lái)看看效果會(huì)是怎么樣的购撼。

運(yùn)行循環(huán)源和自動(dòng)釋放池

對(duì)于runloop跪削,我們知道runloop一定要有源能力保證run起來(lái)以后不立即結(jié)束,而source有三種迂求,自定義源切揭,端口源,計(jì)時(shí)器锁摔。

先加一個(gè)計(jì)時(shí)器試試

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

-(void)createAndConfigObserverInSecondaryThread {

? ? [[NSThread currentThread] setName:@“ test runloop thread”];

? ? NSRunLoop * loop = [NSRunLoop currentRunLoop];

? ? CFRunLoopObserverRef觀察器;

? ? 觀察者= CFRunLoopObserverCreate(CFAllocatorGetDefault()哼审,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? kCFRunLoopAllActivities谐腰,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? true,//重復(fù)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0xFFFFFF涩盾,// CATransaction(2000000)之后

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? YYRunLoopObserverCallBack十气,NULL);

? ? CFRunLoopRef cfrunloop = [循環(huán)getCFRunLoop];

? ? 如果(觀察者){? ? ? ? CFRunLoopAddObserver(cfrunloop,觀察者春霍,kCFRunLoopCommonModes);


? ? ? ? CFRelease(觀察者);

? ? }

? ? [NSTimer scheduleTimerWithTimeInterval:5目標(biāo):自我選擇器:@selector(testAction)userInfo:無(wú)重復(fù):是]砸西;

? ? [循環(huán)運(yùn)行];

? ? NSLog(@“線程結(jié)束”);

}

-(void)testAction {

? ? __autoreleasing id test = [NSObject new];

? ? obj =測(cè)試址儒;

? ? NSLog(@“ obj =%@”芹枷,obj);

}

這里的oberserver沒(méi)有什么,就是從YYKit里復(fù)制出來(lái)的一段觀察者代碼莲趣,用于監(jiān)視r(shí)unloop的狀態(tài)鸳慈。發(fā)現(xiàn)的可以看看。

在testAction()中加上watchpoint斷點(diǎn)喧伞,觀察obj的釋放時(shí)機(jī)走芋。可以看到釋放的時(shí)機(jī)在CFRunloopRunSpecific中潘鲫,也就是runloop切換狀態(tài)的時(shí)候翁逞,繼續(xù)往上看發(fā)現(xiàn)這個(gè)替代。這個(gè)函數(shù)中的實(shí)現(xiàn)如下

__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__()

1

2

3

4

5

6

靜態(tài)void __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION __(CFRunLoopTimerCallBack func溉仑,CFRunLoopTimerRef timer挖函,void * info){

? ? if(func){

? ? ? ? func(timer,info);

? ? }

? ? asm __volatile __(“”); //阻止尾部調(diào)用優(yōu)化

}

這個(gè)所謂func的callback是timer的一個(gè)屬性浊竟,根據(jù)這個(gè)調(diào)用椗不看到浅萧,釋放autoreleasepool的操作應(yīng)該是在這個(gè)callback中。這里猜測(cè)一下timer哲思,應(yīng)該是在自己的回調(diào)函數(shù)里插入了釋放autorelesepool的代碼洼畅。

然后用自己實(shí)現(xiàn)的source試一試,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

-(void)createAndConfigObserverInSecondaryThread {

? ? __autoreleasing id test = [NSObject new];

? ? NSLog(@“ obj =%@”棚赔,測(cè)試);

? ? obj =測(cè)試帝簇;

? ? [[NSThread currentThread] setName:@“ test runloop thread”];

? ? NSRunLoop * loop = [NSRunLoop currentRunLoop];

? ? CFRunLoopObserverRef觀察器靠益;

? ? 觀察者= CFRunLoopObserverCreate(CFAllocatorGetDefault()丧肴,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? kCFRunLoopAllActivities,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? true胧后,//重復(fù)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0xFFFFFF芋浮,// CATransaction(2000000)之后

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? YYRunLoopObserverCallBack,NULL);

? ? CFRunLoopRef cfrunloop = [循環(huán)getCFRunLoop];

? ? 如果(觀察者){? ? ? ? CFRunLoopAddObserver(cfrunloop壳快,觀察者纸巷,kCFRunLoopCommonModes);? ? ? ? CFRelease(觀察者);? ? }? ? CFRunLoopSourceRef源;? ? CFRunLoopSourceContext sourceContext = {0眶痰,(__bridge void *)(self)瘤旨,NULL,NULL竖伯,NULL存哲,NULL,NULL七婴,NULL祟偷,NULL,NULL打厘,&runLoopSourcePerformRoutine};? ? 源= CFRunLoopSourceCreate(NULL肩袍,0,&sourceContext);? ? CFRunLoopAddSource(cfrunloop婚惫,source氛赐,kCFRunLoopDefaultMode);? ? runLoopSource =源;? ? runLoop = cfrunloop;? ? [循環(huán)運(yùn)行];? ? NSLog(@“線程結(jié)束”); }



-(void)wakeupSource {

? ? //通知輸入源

? ? CFRunLoopSourceSignal(runLoopSource);

? ? //喚醒runLoop

? ? CFRunLoopWakeUp(runLoop); }


...

void runLoopSourcePerformRoutine(void * info)

{

? __autoreleasing id test = [NSObject new];

? ? obj =測(cè)試先舷;

? ? //

? ? NSLog(@“ obj is%@”艰管,obj); // //如果不對(duì)obj賦值,obj會(huì)一直持有createAndConfigObserverInSecondaryThread函數(shù)入口的那個(gè)對(duì)象蒋川,那個(gè)對(duì)象不在這里面的自動(dòng)釋放池影響牲芋。

? ? NSLog(@“”方法%@“,[NSThread currentThread]);

}

這里wakeupSource()是一個(gè)按鈕的點(diǎn)擊事件,用于喚醒runloop缸浦。runloop喚醒之后將執(zhí)行runLoopSourcePerformRoutine函數(shù)夕冲,在runLoopSourcePerformRoutine()中觀察對(duì)象的釋放時(shí)機(jī),發(fā)現(xiàn)是在[NSRunloop run:beforeDate:]中裂逐,查看GNU的實(shí)現(xiàn)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

-(BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)date

{

? NSAutoreleasePool * arp = [NSAutoreleasePool new];

? NSString * savedMode = _currentMode;

? GSRunLoopCtxt *上下文歹鱼;

? NSDate * d;

? NSAssert(mode!= nil卜高,NSInvalidArgumentException);

? / *處理所有待處理的通知弥姻。

? * /

? GSPrivateNotifyASAP(mode);

? / *并處理循環(huán)中安排的所有執(zhí)行者(例如,來(lái)自

? 另一個(gè)線程的東西掺涛。

? * /

? _currentMode =模式庭敦;

? context = NSMapGet(_contextMap,mode);

? [self _checkPerformers:context];

? _currentMode = savedMode;

? / *找出我們可以在第一個(gè)限制日期之前等待多長(zhǎng)時(shí)間薪缆。

? *如果沒(méi)有輸入源或計(jì)時(shí)器秧廉,請(qǐng)立即返回。

? * /

? d = [self limitDateForMode:模式];

? if(nil == d)

? ? {

? ? ? [樹(shù)樁排水]拣帽;

? ? ? 返回否疼电;

? ? }

? / *使用我們擁有的兩個(gè)日期中的較早日期(零日期就像遙遠(yuǎn)的過(guò)去)。

? * /

? if(nil == date)

? ? {

? ? ? [self acceptInputForMode:模式beforeDate:nil];

? ? }

? else

? ? {

? ? ? / *保留日期诞外,以防計(jì)時(shí)器(或其他事件)觸發(fā)

? ? ? *。

? ? ? * /

? ? ? d = [[d較早的日期:日期]副本];

? ? ? [self acceptInputForMode:模式beforeDate:d];

? ? ? 發(fā)布(d)灾票;

? ? }

? [排泄口]峡谊;

? 返回是;

}

在GNU的實(shí)現(xiàn)中刊苍,targer執(zhí)行相應(yīng)的動(dòng)作操作是在[self acceptInputForMode: mode beforeDate: d];中既们,可以看到在runMode: (NSString*)mode beforeDate: (NSDate*)date方法中,其實(shí)是包裹了一個(gè)autoreleasepool的正什,也就是arp啥纸,如果在深入一些函數(shù)里面,發(fā)現(xiàn)實(shí)際上很多地方都有autoreleasepool的函數(shù)婴氮,因此即使是我們自定義的源斯棒,執(zhí)行函數(shù)中沒(méi)有釋放autoreleasepool的操作也不用擔(dān)心,系統(tǒng)在各個(gè)關(guān)鍵入口都給我們加了這些操作主经。

文章到此就告一段落了荣暮,還有一種端口源,也就是source1罩驻,這種source我沒(méi)有去看穗酥,好奇的同學(xué)可以去看一看如果有什么不對(duì)我們一起討論。

總結(jié)

1.

在runloop的運(yùn)行中:beforeDate,以及一些源的回調(diào)中砾跃,有autoreleasepool的push和pop操作骏啰,總結(jié)就是系統(tǒng)在1.子線程在使用autorelease對(duì)象時(shí),如果沒(méi)有autoreleasepool會(huì)在autoreleaseNoPage中懶加載一個(gè)出來(lái)抽高。很多地方都差不多自動(dòng)釋放的管理操作判耕。

3.就算插入沒(méi)有彈出也沒(méi)關(guān)系,在線程退出的時(shí)候會(huì)釋放資源厨内,執(zhí)行AutoreleasePoolPage :: tls_dealloc祈秕,在這里面會(huì)清空autoreleasepool。

##參考

深入了解runloop

黑幕背后的自動(dòng)釋放堆棧溢出

流程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雏胃,一起剝皮案震驚了整個(gè)濱河市请毛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞭亮,老刑警劉巖方仿,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異统翩,居然都是意外死亡仙蚜,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門厂汗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)委粉,“玉大人,你說(shuō)我怎么就攤上這事娶桦〖纸冢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵衷畦,是天一觀的道長(zhǎng)栗涂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)祈争,這世上最難降的妖魔是什么斤程? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮菩混,結(jié)果婚禮上忿墅,老公的妹妹穿的比我還像新娘。我一直安慰自己沮峡,他們只是感情好球匕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著帖烘,像睡著了一般亮曹。 火紅的嫁衣襯著肌膚如雪橄杨。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天照卦,我揣著相機(jī)與錄音式矫,去河邊找鬼。 笑死役耕,一個(gè)胖子當(dāng)著我的面吹牛采转,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瞬痘,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼故慈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了框全?” 一聲冷哼從身側(cè)響起察绷,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎津辩,沒(méi)想到半個(gè)月后拆撼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喘沿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年闸度,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚜印。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡莺禁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窄赋,到底是詐尸還是另有隱情哟冬,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布寝凌,位于F島的核電站柒傻,受9級(jí)特大地震影響孝赫,放射性物質(zhì)發(fā)生泄漏较木。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一青柄、第九天 我趴在偏房一處隱蔽的房頂上張望伐债。 院中可真熱鬧,春花似錦致开、人聲如沸峰锁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)虹蒋。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間魄衅,已是汗流浹背峭竣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晃虫,地道東北人皆撩。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像哲银,于是被迫代替她去往敵國(guó)和親扛吞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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