iOS內(nèi)存管理(MRC、ARC)深入淺出

內(nèi)存管理方式

首先明確一點岭皂,無論在MRC還是ARC情況下郊霎,Objective-C采用的是引用計數(shù)式的內(nèi)存管理方式,這一方式的特點:

自己生成的對象爷绘,自己持有书劝。例如:NSObject * __strong obj = [[NSObject alloc]init];。

非自己生成的對象土至,自己也能持有购对。例如:NSMutableArray * __strong array = [NSMutableArray array];。

不再需要自己持有對象時釋放毙籽。

無法釋放非自己持有的對象洞斯。

對象操作Objective-C方法生成并持有對象alloc/new/copy/mutableCopy等方法持有對象retain方法釋放對象release方法廢棄對象dealloc方法

自己生成的對象,自己持有

在iOS內(nèi)存管理中有四個關(guān)鍵字坑赡,alloc、new么抗、copy、mutableCopy,自身使用這些關(guān)鍵字產(chǎn)生對象,那么自身就持有了對象

// 使用了alloc分配了內(nèi)存氯质,obj指向了對象直焙,該對象本身引用計數(shù)為1,不需要retain

id obj = [[NSObject alloc] init];

// 使用了new分配了內(nèi)存,objc指向了對象,該對象本身引用計數(shù)為1,不需要retain

id obj = [NSObject new];

非自己生成的對象捆探,自己也能持有

// NSMutableArray通過類方法array產(chǎn)生了對象(并沒有使用alloc然爆、new、copy黍图、mutableCopt來產(chǎn)生對象),因此該對象不屬于obj自身產(chǎn)生的

// 因此曾雕,需要使用retain方法讓對象計數(shù)器+1,從而obj可以持有該對象(盡管該對象不是他產(chǎn)生的)

id obj = [NSMutableArray array];

[obj retain];

不再需要自己持有對象時釋放

id obj = [NSMutableArray array];?

[obj retain];

// 當(dāng)obj不在需要持有的對象,那么助被,obj應(yīng)該發(fā)送release消息

[obj release];

// 釋放了對象還進行釋放,會導(dǎo)致奔潰

[obj release];

無法釋放非自己持有的對象

// 釋放一個不屬于自己的對象

id obj = [NSMutableArray array];

// obj沒有進行retain操作而進行release操作剖张,然后autoreleasePool也會對其進行一次release操作,導(dǎo)致奔潰揩环。

后面會講到autorelease搔弄。

[obj release];

針對[NSMutableArray array]方法取得的對象存在,自己卻不持有對象丰滑,底層大致實現(xiàn):

+ (id)object {

//自己持有對象

id obj = [[NSObject alloc]init];

[obj autorelease];

//取得的對象存在顾犹,但自己不持有對象

return obj;

}

使用了autorelease方法,將obj注冊到autoreleasePool中褒墨,不會立即釋放蹦渣,當(dāng)pool結(jié)束時再自動調(diào)用release。這樣達到取得的對象存在貌亭,自己不持有對象柬唯。

autorelease

顧名思義:autorelease就是自動釋放,它和C語言的局部變量類似圃庭,C語言局部變量在程序執(zhí)行時锄奢,超出其作用域時,會被自動廢棄剧腻。autorelease會像C語言局部變量那樣對待對象實例拘央,當(dāng)超出作用域時,對象實例的release實例方法會被調(diào)用书在。我們可以設(shè)定autorelease的作用域灰伟。

autorelease具體使用方法

生成并持有NSAutoreleasePool對象

調(diào)用已分配對象的autorelease實例方法

廢棄NSAutoreleasePool對象

NSAutoreleasePool生命周期

NSAutoreleasePool對象的生命周期就是一個作用域,對于所有調(diào)用過autorelease實例方法的對象儒旬,在廢棄NSAutoreleasePool對象時栏账,都會調(diào)用其release實例方法。如上圖所示栈源。

用源代碼表示如下:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

id obj = [[NSObject alloc] init];

[obj autorelease];

[pool drain];

在[pool drain]調(diào)用時挡爵,NSAutoreleasePool被銷毀,obj的release方法會被觸發(fā)甚垦。obj被釋放茶鹃。

autorelease蘋果實現(xiàn)

可以通過objc4庫的runtime/objc-arr.mm來確認蘋果中autorelease的實現(xiàn)涣雕。

class AutoreleasePoolPage

{

static inline void *push()

{

相當(dāng)于生成或持有NSAutoreleasePool類對象

}

static inline void *pop(void *token)

{

相當(dāng)于廢棄NSAutoreleasePool類對象

releaseAll();

}

static inline id autorelease(id obj)

{

相當(dāng)于NSAutoreleasePool類的addObject類方法?

AutoreleasePoolPage *autoreleasePoolPage = 取得正在使用的AutoreleasePoolPage實例;

autoreleasePoolPage->add(obj);

}

id *add(id obj)

{

將對象追加到內(nèi)部數(shù)組中

}

void releaseAll()

{

調(diào)用內(nèi)部數(shù)組中對象的release實例方法

}

};

void *objc_autoreleasePoolPush(void)

{

return AutoreleasePoolPage::push();

}

void objc_autoreleasePoolPop(void *ctxt)

{

AutoreleasePoolPage::pop(ctxt);

}

id *objc_autorelease(id obj)

{

return AutoreleasePoolPage::autorelease(obj);

}

我們使用調(diào)速器來觀察NSAutoreleasePool類方法和autorelease方法的運行過程,如下所示闭翩,這些方法調(diào)用了關(guān)聯(lián)于objc4庫autorelease實現(xiàn)的函數(shù)挣郭。

//等同于objc_autoreleasePoolPush()

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

id obj = [[NSObject alloc] init];

//等同于objc_autorelease(obj)

[obj autorelease];

//等同于objc_autoreleasePoolPop(pool)

[pool drain];

在iOS程序啟動后,主線程會自動創(chuàng)建一個RunLoop疗韵,蘋果在主線程 RunLoop 里注冊了兩個 Observer兑障,其回調(diào)都是 _wrapRunLoopWithAutoreleasePoolHandler()。

第一個 Observer 監(jiān)視的事件是 Entry(即將進入Loop)伶棒,其回調(diào)內(nèi)會調(diào)用 _objc_autoreleasePoolPush() 創(chuàng)建自動釋放池旺垒。其 order 是-2147483647,優(yōu)先級最高肤无,保證創(chuàng)建釋放池發(fā)生在其他所有回調(diào)之前先蒋。

第二個 Observer 監(jiān)視了兩個事件: BeforeWaiting(準備進入休眠) 時調(diào)用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 釋放舊的池并創(chuàng)建新池;Exit(即將退出Loop) 時調(diào)用 _objc_autoreleasePoolPop() 來釋放自動釋放池宛渐。這個 Observer 的 order 是 2147483647竞漾,優(yōu)先級最低,保證其釋放池子發(fā)生在其他所有回調(diào)之后窥翩。

在主線程執(zhí)行的代碼业岁,通常是寫在諸如事件回調(diào)、Timer回調(diào)內(nèi)的寇蚊。這些回調(diào)會被 RunLoop 創(chuàng)建好的 AutoreleasePool 環(huán)繞著笔时,所以不會出現(xiàn)內(nèi)存泄漏,開發(fā)者也不一定非得顯示創(chuàng)建 Pool 了仗岸。runloop相關(guān)

盡管如此允耿,在大量產(chǎn)生autorelease的對象時,只要NSAutoreleasePool沒有被廢棄扒怖,那么產(chǎn)生的對象就不能被釋放较锡,因此會產(chǎn)生內(nèi)存不足的現(xiàn)象。例如:

讀入大量圖像的同時改變其尺寸盗痒。圖像文件讀入到NSData對象蚂蕴,并從中生成UIImage對象,改變該對象尺寸后生成新的UIImage對象俯邓。這種情況會產(chǎn)生大量autorelease對象骡楼。

for (int i = 0; i < 圖片數(shù); ++ i) {

/*

讀入圖片

大量產(chǎn)生autorelease的對象

由于沒有廢棄NSAutoreleasePool對象

導(dǎo)致產(chǎn)生內(nèi)存峰值,可能內(nèi)存不足而奔潰

*/

}

在這種情況下看成,應(yīng)當(dāng)在適當(dāng)?shù)奈恢蒙删唷⒊钟谢驈U棄NSAutoreleasePool對象

for (int i = 0; i < 圖片數(shù); ++ i) {

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

/*

讀入圖片

大量產(chǎn)生autorelease的對象

*/

[pool drain];

/*

通過釋放pool

autorelease的對象被release,就不會產(chǎn)生內(nèi)存峰值

*/

}

使用容器的block版本的枚舉器時川慌,內(nèi)部會自動添加一個AutoreleasePool:

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

// 這里被一個局部@autoreleasepool包圍著

}];

所有權(quán)修飾符及其原理

在 ARC 特性下有 4 種與內(nèi)存管理息息相關(guān)的變量所有權(quán)修飾符值得我們關(guān)注:

__strong

__weak

__unsafe_unretaied

__autoreleasing

說到變量所有權(quán)修飾符吃嘿,有人可能會跟屬性修飾符搞混,這里做一個對照關(guān)系小結(jié):

assign 對應(yīng)的所有權(quán)類型是 __unsafe_unretained梦重。

copy 對應(yīng)的所有權(quán)類型是 __strong兑燥。

retain 對應(yīng)的所有權(quán)類型是 __strong。

strong 對應(yīng)的所有權(quán)類型是 __strong琴拧。

unsafe_unretained對應(yīng)的所有權(quán)類型是__unsafe_unretained降瞳。

weak 對應(yīng)的所有權(quán)類型是 __weak。

__strong

__strong 表示強引用蚓胸,對應(yīng)定義 property 時用到的 strong挣饥。當(dāng)對象沒有任何一個強引用指向它時,它才會被釋放沛膳。如果在聲明引用時不加修飾符扔枫,那么引用將默認是強引用。當(dāng)需要釋放強引用指向的對象時锹安,需要保證所有指向?qū)ο髲娨弥脼?nil短荐。__strong 修飾符是 id 類型和對象類型默認的所有權(quán)修飾符。

原理:

{

id __strong obj = [[NSObject alloc] init];

}

//編譯器的模擬代碼

id obj = objc_msgSend(NSObject,@selector(alloc));

objc_msgSend(obj,@selector(init));

// 出作用域的時候調(diào)用

objc_release(obj);

雖然ARC有效時不能使用release方法叹哭,但由此可知編譯器自動插入了release忍宋。

對象是通過除alloc、new风罩、copy糠排、multyCopy外方法產(chǎn)生的情況

{

id __strong obj = [NSMutableArray array];

}

結(jié)果與之前稍有不同:

//編譯器的模擬代碼

id obj = objc_msgSend(NSMutableArray,@selector(array));

objc_retainAutoreleasedReturnValue(obj);

objc_release(obj);

objc_retainAutoreleasedReturnValue函數(shù)主要用于優(yōu)化程序的運行。它是用于持有(retain)對象的函數(shù)超升,它持有的對象應(yīng)為返回注冊在autoreleasePool中對象的方法入宦,或是函數(shù)的返回值。像該源碼這樣廓俭,在調(diào)用array類方法之后云石,由編譯器插入該函數(shù)。

而這種objc_retainAutoreleasedReturnValue函數(shù)是成對存在的研乒,與之對應(yīng)的函數(shù)是objc_autoreleaseReturnValue汹忠。它用于array類方法返回對象的實現(xiàn)上。下面看看NSMutableArray類的array方法通過編譯器進行了怎樣的轉(zhuǎn)換:

+ (id)array

{

return [[NSMutableArray alloc] init];

}

//編譯器模擬代碼

+ (id)array

{

id obj = objc_msgSend(NSMutableArray,@selector(alloc));

objc_msgSend(obj,@selector(init));

// 代替我們調(diào)用了autorelease方法

return objc_autoreleaseReturnValue(obj);

}

我們可以看見調(diào)用了objc_autoreleaseReturnValue函數(shù)且這個函數(shù)會返回注冊到自動釋放池的對象雹熬,但是宽菜,這個函數(shù)有個特點,它會查看調(diào)用方的命令執(zhí)行列表竿报,如果發(fā)現(xiàn)接下來會調(diào)用objc_retainAutoreleasedReturnValue則不會將返回的對象注冊到autoreleasePool中而僅僅返回一個對象铅乡。達到了一種最優(yōu)效果。如下圖:

省略了autoreleasePool注冊

__weak

__weak 表示弱引用烈菌,對應(yīng)定義 property 時用到的 weak阵幸。弱引用不會影響對象的釋放花履,而當(dāng)對象被釋放時,所有指向它的弱引用都會自定被置為 nil挚赊,這樣可以防止野指針诡壁。使用__weak修飾的變量,即是使用注冊到autoreleasePool中的對象荠割。__weak 最常見的一個作用就是用來避免循環(huán)循環(huán)妹卿。需要注意的是,__weak 修飾符只能用于 iOS5 以上的版本蔑鹦,在 iOS4 及更低的版本中使用 __unsafe_unretained 修飾符來代替夺克。

__weak 的幾個使用場景:

在 Delegate 關(guān)系中防止循環(huán)引用。

在 Block 中防止循環(huán)引用嚎朽。

用來修飾指向由 Interface Builder 創(chuàng)建的控件铺纽。比如:@property (weak, nonatomic) IBOutlet UIButton *testButton;。

原理

{

id __weak obj = [[NSObject alloc] init];

}

編譯器轉(zhuǎn)換后的代碼如下:

id obj;

id tmp = objc_msgSend(NSObject,@selector(alloc));

objc_msgSend(tmp,@selector(init));

objc_initweak(&obj,tmp);

objc_release(tmp);

objc_destroyWeak(&object);

對于__weak內(nèi)存管理也借助了類似于引用計數(shù)表的散列表火鼻,它通過對象的內(nèi)存地址做為key室囊,而對應(yīng)的__weak修飾符變量的地址作為value注冊到weak表中,在上述代碼中objc_initweak就是完成這部分操作魁索,而objc_destroyWeak

則是銷毀該對象對應(yīng)的value融撞。當(dāng)指向的對象被銷毀時,會通過其內(nèi)存地址粗蔚,去weak表中查找對應(yīng)的__weak修飾符變量尝偎,將其從weak表中刪除。所以鹏控,weak在修飾只是讓weak表增加了記錄沒有引起引用計數(shù)表的變化.

對象通過objc_release釋放對象內(nèi)存的動作如下:

objc_release

因為引用計數(shù)為0所以執(zhí)行dealloc

_objc_rootDealloc

objc_dispose

objc_destructInstance

objc_clear_deallocating

而在對象被廢棄時最后調(diào)用了objc_clear_deallocating致扯,該函數(shù)的動作如下:

從weak表中獲取已廢棄對象內(nèi)存地址對應(yīng)的所有記錄

將已廢棄對象內(nèi)存地址對應(yīng)的記錄中所有以weak修飾的變量都置為nil

從weak表刪除已廢棄對象內(nèi)存地址對應(yīng)的記錄

根據(jù)已廢棄對象內(nèi)存地址從引用計數(shù)表中找到對應(yīng)記錄刪除

據(jù)此可以解釋為什么對象被銷毀時對應(yīng)的weak指針變量全部都置為nil,同時当辐,也看出來銷毀weak步驟較多抖僵,如果大量使用weak的話會增加CPU的負荷。

還需要確認一點是:__weak修飾符的變量缘揪,即是使用注冊到autoreleasePool中的對象耍群。

{

id __weak obj1 = obj;

NSLog(@"obj2-%@",obj1);

}

編譯器轉(zhuǎn)換上述代碼如下:

id obj1;

objc_initweak(&obj1,obj);

id tmp = objc_loadWeakRetained(&obj1);

objc_autorelease(tmp);

NSLog(@"%@",tmp);

objc_destroyWeak(&obj1);

objc_loadWeakRetained函數(shù)獲取附有__weak修飾符變量所引用的對象并retain, objc_autorelease函數(shù)將對象放入autoreleasePool中,據(jù)此當(dāng)我們訪問weak修飾指針指向的對象時找筝,實際上是訪問注冊到自動釋放池的對象蹈垢。因此,如果大量使用weak的話袖裕,在我們?nèi)ピL問weak修飾的對象時曹抬,會有大量對象注冊到自動釋放池,這會影響程序的性能。

解決方案:要訪問weak修飾的變量時急鳄,先將其賦給一個strong變量谤民,然后進行訪問

為什么訪問weak修飾的對象就會訪問注冊到自動釋放池的對象呢?

因為weak不會引起對象的引用計數(shù)器變化堰酿,因此,該對象在運行過程中很有可能會被釋放赖临。所以胞锰,需要將對象注冊到自動釋放池中并在autoreleasePool銷毀時釋放對象占用的內(nèi)存灾锯。

__unsafe_unretained

ARC 是在 iOS5 引入的兢榨,而 __unsafe_unretained 這個修飾符主要是為了在ARC剛發(fā)布時兼容iOS4以及版本更低的系統(tǒng),因為這些版本沒有弱引用機制顺饮。這個修飾符在定義property時對應(yīng)的是unsafe_unretained吵聪。__unsafe_unretained 修飾的指針純粹只是指向?qū)ο螅瑳]有任何額外的操作兼雄,不會去持有對象使得對象的 retainCount +1吟逝。而在指向的對象被釋放時依然原原本本地指向原來的對象地址,不會被自動置為 nil赦肋,所以成為了野指針块攒,非常不安全。

__unsafe_unretained 的應(yīng)用場景:

在 ARC 環(huán)境下但是要兼容 iOS4.x 的版本佃乘,用__unsafe_unretained 替代 __weak 解決強循環(huán)循環(huán)的問題囱井。

__autoreleasing

將對象賦值給附有__autoreleasing修飾符的變量等同于MRC時調(diào)用對象的autorelease方法。

@autoeleasepool {

// 如果看了上面__strong的原理趣避,就知道實際上對象已經(jīng)注冊到自動釋放池里面了

id __autoreleasing obj = [[NSObject alloc] init];

}

編譯器轉(zhuǎn)換上述代碼如下:

id pool = objc_autoreleasePoolPush();

id obj = objc_msgSend(NSObject,@selector(alloc));

objc_msgSend(obj,@selector(init));

objc_autorelease(obj);

objc_autoreleasePoolPop(pool);

@autoreleasepool {

id __autoreleasing obj = [NSMutableArray array];

}

編譯器轉(zhuǎn)換上述代碼如下:

id pool = objc_autoreleasePoolPush();

id obj = objc_msgSend(NSMutableArray,@selector(array));

objc_retainAutoreleasedReturnValue(obj);

objc_autorelease(obk);

objc_autoreleasePoolPop(pool);

上面兩種方式庞呕,雖然第二種持有對象的方法從alloc方法變?yōu)榱薿bjc_retainAutoreleasedReturnValue函數(shù),都是通過objc_autorelease程帕,注冊到autoreleasePool中住练。

ARC 模式規(guī)則

ARC 模式下,還有一些需要注意的規(guī)則:

不能顯式使用 retain/release/retainCount/autorelease愁拭。

不能使用 NSAllocateObject/NSDeallocateObject讲逛。

需要遵守內(nèi)存管理的方法命名規(guī)則。在 ARC 模式和 MRC 模式下岭埠,以 alloc/new/copy/mutableCopy 開頭的方法在返回對象時都必須返回給調(diào)用方所應(yīng)當(dāng)持有的對象盏混。在 ARC 模式下,追加一條:以 init 開頭的方法必須是實例方法并且必須要返回對象枫攀。返回的對象應(yīng)為 id 類型或聲明該方法的類的對象類型括饶,或是該類的超類型或子類型。該返回的對象并不注冊到 Autorelease Pool 中来涨,基本上只是對 alloc 方法返回值的對象進行初始化處理并返回該對象图焰。需要注意的是:- (void)initialize; 方法雖然是以 init 開頭但是并不包含在上述規(guī)則中。

不要顯式調(diào)用 dealloc蹦掐。

使用 @autoreleasepool 塊替代 NSAutoreleasePool技羔。

不能使用區(qū)域(NSZone)僵闯。

對象型變量不能作為 C 語言結(jié)構(gòu)體(struct/union)的成員。

顯式轉(zhuǎn)換 id 和 void *藤滥。

Toll-Free Bridging

MRC 下的 Toll-Free Bridging 因為不涉及內(nèi)存管理的轉(zhuǎn)移鳖粟,相互之間可以直接交換使用,當(dāng)使用 ARC 時拙绊,由于Core Foundation 框架并不支持 ARC向图,此時編譯器不知道該如何處理這個同時有 ObjC 指針和 CFTypeRef 指向的對象,所以除了轉(zhuǎn)換類型标沪,還需指定內(nèi)存管理所有權(quán)的改變榄攀,可通過 __bridge、__bridge_retained 和 CFBridgingRetain金句、__bridge_transfer 和 CFBridgingRelease檩赢。

__bridge

只是聲明類型轉(zhuǎn)變,但是不做內(nèi)存管理規(guī)則的轉(zhuǎn)變违寞。比如:

CFStringRef s1 = (__bridge CFStringRef) [[NSString alloc] initWithFormat:@"Hello, %@!", name];

只是做了 NSString 到 CFStringRef 的轉(zhuǎn)化贞瞒,但管理規(guī)則未變,依然要用 Objective-C 類型的 ARC 來管理 s1趁曼,你不能用 CFRelease() 去釋放 s1军浆。

__bridge_retained or CFBridgingRetain

表示將指針類型轉(zhuǎn)變的同時,將內(nèi)存管理的責(zé)任由原來的 Objective-C 交給Core Foundation 來處理彰阴,也就是瘾敢,將 ARC 轉(zhuǎn)變?yōu)?MRC。比如尿这,還是上面那個例子

NSString *s1 = [[NSString alloc] initWithFormat:@"Hello, %@!", name];

CFStringRef s2 = (__bridge_retained CFStringRef)s1;

// or CFStringRef s2 = (CFStringRef)CFBridgingRetain(s1);

// do something with s2

//...

CFRelease(s2); // 注意要在使用結(jié)束后加這個

我們在第二行做了轉(zhuǎn)化簇抵,這時內(nèi)存管理規(guī)則由 ARC 變?yōu)榱?MRC,我們需要手動的來管理 s2 的內(nèi)存射众,而對于 s1碟摆,我們即使將其置為 nil,也不能釋放內(nèi)存叨橱。

__bridge_transfer or CFBridgingRelease

這個修飾符和函數(shù)的功能和上面那個 __bridge_retained 相反典蜕,它表示將管理的責(zé)任由 Core Foundation 轉(zhuǎn)交給 Objective-C,即將管理方式由 MRC 轉(zhuǎn)變?yōu)?ARC罗洗。比如:

CFStringRef result = CFURLCreateStringByAddingPercentEscapes(. . .);

NSString *s = (__bridge_transfer NSString *)result;

//or NSString *s = (NSString *)CFBridgingRelease(result);

return s;

這里我們將 result 的管理責(zé)任交給了 ARC 來處理愉舔,我們就不需要再顯式地將 CFRelease() 了。

其他

之前寫的和內(nèi)存管理有些許相關(guān):為什么聲明NString伙菜,NSArray等需要使用copy轩缤,使用strong有什么問題,深拷貝和淺拷貝,block為什么使用copy火的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壶愤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子馏鹤,更是在濱河造成了極大的恐慌征椒,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件湃累,死亡現(xiàn)場離奇詭異勃救,居然都是意外死亡,警方通過查閱死者的電腦和手機脱茉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門剪芥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人琴许,你說我怎么就攤上這事「榷悖” “怎么了榜田?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锻梳。 經(jīng)常有香客問我箭券,道長,這世上最難降的妖魔是什么疑枯? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任辩块,我火速辦了婚禮,結(jié)果婚禮上荆永,老公的妹妹穿的比我還像新娘废亭。我一直安慰自己,他們只是感情好具钥,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布豆村。 她就那樣靜靜地躺著,像睡著了一般骂删。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宁玫,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天粗恢,我揣著相機與錄音,去河邊找鬼欧瘪。 笑死眷射,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凭迹,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼罚屋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嗅绸?” 一聲冷哼從身側(cè)響起脾猛,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鱼鸠,沒想到半個月后猛拴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡蚀狰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年愉昆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片麻蹋。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡跛溉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扮授,到底是詐尸還是另有隱情芳室,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布刹勃,位于F島的核電站堪侯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏荔仁。R本人自食惡果不足惜伍宦,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乏梁。 院中可真熱鬧次洼,春花似錦、人聲如沸掌呜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽质蕉。三九已至势篡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間模暗,已是汗流浹背禁悠。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留兑宇,地道東北人碍侦。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瓷产。 傳聞我的和親對象是個殘疾皇子站玄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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