Objective-C高級(jí)編程(上):ARC

《Objective-C高級(jí)編程:iOS與OS X多線程和內(nèi)存管理》是iOS開發(fā)中一本經(jīng)典書籍吃型,書中有關(guān)ARC、Block、GCD的梳理是iOS開發(fā)進(jìn)階路上必不可少的知識(shí)儲(chǔ)備。筆者讀完此書后為了加強(qiáng)理解,特以筆記記之邑时。本文為開篇,圍繞ARC談起Objective-C中的內(nèi)存管理特姐。

ARC

鑒于本書翻譯自日文原版且翻譯偏向書面晶丘,筆者希望采用通俗的語言記錄,文章結(jié)構(gòu)略有調(diào)整唐含。

本文首發(fā)于Rachal's blog浅浮。

內(nèi)存管理

ARC(自動(dòng)引用計(jì)數(shù))是iOS5、macOS10.7引入的內(nèi)存管理技術(shù)捷枯,為了循序漸進(jìn)的方式了解這項(xiàng)技術(shù)滚秩,本書先從ARC無效的環(huán)境說起递惋,也就是常指的MRC(手動(dòng)引用計(jì)數(shù))環(huán)境坑匠。

本書開篇沒有直接提及引用計(jì)數(shù)的概念,而是以辦公室開燈關(guān)燈的例子引出內(nèi)存管理的思考方式惊来。作者認(rèn)為理解內(nèi)存管理時(shí)把注意力落在“生成”攀痊、“持有”桐腌、“釋放”等管理操作上更為客觀。

內(nèi)存管理的思考方式

  • 自己生成的對(duì)象蚕苇,自己所持有哩掺。
  • 非自己生成的對(duì)象,自己也能持有涩笤。
  • 不再需要自己持有的對(duì)象時(shí)釋放嚼吞。
  • 非自己持有的對(duì)象無法釋放。

這里的“自己”理解為編程人員自身蹬碧。與“生成”舱禽、“持有”、“釋放”操作并列的還有“廢棄”恩沽,分別對(duì)應(yīng)以下方法:

對(duì)象操作 Objective-C方法
生成并持有對(duì)象 alloc/new/copy/mutableCopy等方法
持有對(duì)象 retain方法
釋放對(duì)象 release方法
廢棄對(duì)象 dealloc方法
  • 注意:以上方法包含在Cocoa框架中而非Objective-C語言中誊稚。

自己生成的對(duì)象,自己所持有

以下面名稱開頭的方法生成的對(duì)象為自己持有:

  • alloc
  • new
  • copy
  • mutableCopy
id obj1 = [[NSObject alloc] init];// 自己生成并持有
id obj2 = [NSObject new];// 自己生成并持有

另外罗心,根據(jù)以上原則里伯,下列方法也意味著自己生成并持有對(duì)象:

  • allocMyObject
  • newThatObject
  • copyThis
  • mutableCopyYourObject
id obj = [MyObject allocMyObject];

// 內(nèi)部實(shí)現(xiàn)
+ (MyObject *)allocMyObject {
    MyObject *obj = [[MyObject alloc] init];
    return obj;
}

非自己生成的對(duì)象,自己也能持有

alloc/new/copy/mutableCopy以外方法取得對(duì)象渤闷,非自己生成疾瓮,自己不持有對(duì)象§可以通過retain方法為自己所持有狼电。

id obj = [NSMutableArray array];// 取得對(duì)象蜒灰,但自己不持有
[obj retain];// 自己持有對(duì)象

不再需要自己持有的對(duì)象時(shí)釋放

自己持有的對(duì)象不再需要時(shí),持有者有義務(wù)將其釋放肩碟。釋放使用release方法强窖。

id obj = [[NSObject alloc] init];// 自己生成并持有對(duì)象
[obj release];// 釋放對(duì)象

retain方法持有對(duì)象,一旦不再需要削祈,務(wù)必要用release方法釋放翅溺。

id obj = [NSMutableArray array];// 取得對(duì)象,但自己不持有
[obj retain];// 持有非自己生成對(duì)象
[obj release];// 釋放對(duì)象

類似[NSMutableArray array]方法取得的對(duì)象存在岩瘦,但自己不持有對(duì)象未巫,內(nèi)部如何實(shí)現(xiàn)窿撬?以object這個(gè)方法名為例:

- (id)object {
    id obj = [[NSObject alloc] init];// 自己持有
    [obj autorelease];// 適當(dāng)時(shí)機(jī)自動(dòng)釋放
    return obj;// 取得對(duì)象存在启昧,但自己不持有
}

autorelease提供這樣的功能,使對(duì)象在超出指定的生存范圍時(shí)能夠自動(dòng)并正確地釋放劈伴。
使用NSMutableArray類的array類方法等可以取得誰都不持有的對(duì)象密末,這些方法是通過autorelease實(shí)現(xiàn)的。

非自己持有的對(duì)象無法釋放

alloc/new/copy/mutableCopy方法生成并持有的對(duì)象跛璧,或用retain方法持有的對(duì)象严里,在不需要時(shí)要將其釋放。倘若在應(yīng)用程序中釋放了非自己持有的對(duì)象會(huì)造成崩潰追城。

id obj = [[NSObject alloc] init];// 自己生成并持有對(duì)象
[obj release];// 釋放對(duì)象
[obj release];// 重復(fù)釋放對(duì)象刹碾,崩潰
id obj1 = [obj0 object];// 取得對(duì)象,但自己不持有
[obj1 release];// 釋放非自己持有的對(duì)象座柱,崩潰

alloc/retain/release/dealloc及其實(shí)現(xiàn)

Cocoa是macOS的系統(tǒng)框架迷帜,在iOS上被稱為Cocoa Touch。Cocoa框架雖然沒有公開色洞,但是可以通過Cocoa框架的互換框架GNUstep來推測(cè)蘋果的實(shí)現(xiàn)戏锹。

alloc調(diào)用allocWithZone,那么這里的參數(shù)類型NSZone是什么火诸?

它是為了防止內(nèi)存碎片化而引入的結(jié)構(gòu)锦针。對(duì)內(nèi)存分配的區(qū)域本身進(jìn)行多重化的管理,根據(jù)使用對(duì)象的目的置蜀、對(duì)象的大小分配內(nèi)存奈搜,從而提高內(nèi)存管理的效率。
現(xiàn)在運(yùn)行時(shí)系統(tǒng)中的內(nèi)存管理已經(jīng)極具效率盯荤,使用區(qū)域來管理內(nèi)存反而會(huì)引起內(nèi)存使用效率低下以及源代碼復(fù)雜等問題馋吗。

GNUstep的實(shí)現(xiàn)

GNUstep源碼里alloc類方法用obj_layout結(jié)構(gòu)體中的整數(shù)變量retained來保存引用計(jì)數(shù)retainCount,并將其寫入對(duì)象內(nèi)存頭部廷雅。

執(zhí)行alloc后對(duì)象的實(shí)例方法retainCount獲得數(shù)值是1耗美,retain使變量retained值+1京髓,release使變量retained值-1。release使tetained變量大于0時(shí)-1商架,等于0時(shí)調(diào)用dealloc實(shí)例方法堰怨,廢棄對(duì)象。

具體總結(jié)如下:

  • 在Objective-C的對(duì)象中存有引用計(jì)數(shù)這一整數(shù)值蛇摸。
  • 調(diào)用alloc或是retain方法后备图,引用計(jì)數(shù)值+1。
  • 調(diào)用release后赶袄,引用計(jì)數(shù)值-1揽涮。
  • 引用計(jì)數(shù)值為0時(shí),調(diào)用dealloc方法廢棄對(duì)象饿肺。

蘋果的實(shí)現(xiàn)

alloc過程設(shè)置斷點(diǎn)追蹤調(diào)用的方法和函數(shù):

+alloc
+allocWithZone:
class_createInstance
calloc//分配內(nèi)存塊

蘋果對(duì)alloc的實(shí)現(xiàn)與GNUstep并無多大差異蒋困。

retainCount/retain/release調(diào)用的方法和函數(shù)分別如下:

-retainCount
__CFDoExternRefOperation
CFBasicHashGetCountOfKey
-retain
__CFDoExternRefOperation
CFBasicHashAddValue
-release
__CFDoExternRefOperation
CFBasicHashRemoveValue
(CEBasicHashRemoveValue返回0時(shí),-release 調(diào)用dealloc)

可以從__CFDoExternRefOperation函數(shù)以及一些CFBasicHash開頭的函數(shù)名看出敬辣,蘋果的實(shí)現(xiàn)大概就是采用散列表(又稱哈希表)來管理引用計(jì)數(shù)雪标。

在引用計(jì)數(shù)表中,key為內(nèi)存塊地址溉跃,value為對(duì)應(yīng)的引用計(jì)數(shù)村刨,蘋果這樣實(shí)現(xiàn)的優(yōu)勢(shì)在于:

  • 為對(duì)象分配內(nèi)存塊時(shí)無需考慮內(nèi)存塊頭部。
  • 對(duì)象占用內(nèi)存塊損壞時(shí)撰茎,可以根據(jù)引用計(jì)數(shù)表來確認(rèn)內(nèi)存塊的位置嵌牺。
  • 檢測(cè)內(nèi)存泄露時(shí),根據(jù)引用計(jì)數(shù)表中的記錄檢查對(duì)象的持有者是否存在龄糊。

autorelease及其實(shí)現(xiàn)

autorelease會(huì)像C語言的自動(dòng)變量那樣對(duì)待對(duì)象實(shí)例逆粹。當(dāng)超出其作用域時(shí),對(duì)象實(shí)例的release實(shí)例方法被調(diào)用绎签。

autorelease具體使用方法如下:

  • 1.生成并持有NSAutoreleasePool對(duì)象枯饿;
  • 2.調(diào)用已分配對(duì)象的autorelease實(shí)例方法;
  • 3.廢棄NSAutoreleasePool對(duì)象诡必。
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id obj = [[NSObject alloc] init];
[obj release];
[pool drain];

Cocoa框架中程序主循環(huán)的NSRunLoop對(duì)NSAutoreleasePool對(duì)象進(jìn)行生成奢方、持有和廢棄處理。在大量產(chǎn)生autorelease對(duì)象時(shí)爸舒,若不廢棄NSAutoreleasePool對(duì)象蟋字,那么生成的對(duì)象就不能被廢棄,會(huì)產(chǎn)生內(nèi)存不足現(xiàn)象扭勉。

GNUstep的實(shí)現(xiàn)

autorelease實(shí)例方法的本質(zhì)就是調(diào)用NSAutoreleasePool對(duì)象的addObject類方法鹊奖。

[obj autorelease];

源碼:

- (id)autorelease {
    [NSAutoreleasePool addObject:self];
}

GNUstep在實(shí)現(xiàn)NSAutoreleasePool時(shí)使用連接列表,可以理解為數(shù)組涂炎。若調(diào)用NSObject類的autorelease方法忠聚,該對(duì)象就會(huì)被追加到正在使用的NSAutoreleasePool對(duì)象的數(shù)組中设哗。drain實(shí)例方法廢棄正在使用的NSAutoreleasePool對(duì)象,會(huì)對(duì)數(shù)組中的所有對(duì)象調(diào)用release方法两蟀。

蘋果的實(shí)現(xiàn)

autoreleasepool以數(shù)組的形式實(shí)現(xiàn)网梢,主要通過以下3個(gè)函數(shù):

  • obj_autoreleasePoolPush()
  • obj_autorelease(obj)
  • obj_autoreleasePoolPop(pool)
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/* 等同于objc_autoreleasePoolPush */

id obj = [[NSObject alloc] init];

[obj autorelease];
/* 等同于 objc_autorelease(obj) */

[pool drain];
/* 等同于 objc_autoreleasePoolPop(pool) */

以上是MRC環(huán)境下的內(nèi)存管理及實(shí)現(xiàn)。

ARC

ARC概述

ARC(Auto Reference Counting)是iOS5赂毯、macOS10.7(OS X Lion)引入的內(nèi)存管理技術(shù)战虏。

ARC的出現(xiàn)解決了原來需要手動(dòng)鍵入retainrelease操作的問題。這在降低程序崩潰党涕、內(nèi)存風(fēng)險(xiǎn)的同時(shí)烦感,很大程度上減少了開發(fā)程序的工作量。

內(nèi)存管理的思考方式

“引用計(jì)數(shù)式內(nèi)存管理”的本質(zhì)在ARC中并沒有改變膛堤,ARC只是自動(dòng)地幫我們處理“引用計(jì)數(shù)”的相關(guān)部分手趣。

  • 自己生成的對(duì)象,自己所持有骑祟。
  • 非自己生成的對(duì)象回懦,自己也能持有。
  • 不再需要自己持有的對(duì)象時(shí)釋放次企。
  • 非自己持有的對(duì)象無法釋放。

所有權(quán)修飾符

ARC環(huán)境下其類型必須附加所有權(quán)修飾符(有省略的情況)潜圃,所有權(quán)修飾符有以下4種:

  • __strong
  • __weak
  • __unsafe_unretained
  • __autorelease

書中此處提到id類型做一下記錄:

Objective-C中為了處理對(duì)象缸棵,可將變量定義為id類型,id類型用于隱藏對(duì)象類型的類名部分谭期,相當(dāng)于C語言中常用到的void *堵第。

__strong修飾符

id和對(duì)象類型默認(rèn)使用__strong修飾,由于是默認(rèn)情況隧出,可省略不寫踏志。

__strong表示對(duì)對(duì)象的強(qiáng)引用。持有強(qiáng)引用的變量在超出其作用域時(shí)被廢棄胀瞪。

__strong__weak针余、__autoreleasing一樣,可以保證被修飾的變量在初始化時(shí)為nil凄诞。

id obj = [[NSObject alloc] init];

//等同于
//id __strong obj = [[NSObject alloc] init];

__weak修飾符

循環(huán)引用容易引起內(nèi)存泄漏圆雁。所謂內(nèi)存泄漏就是應(yīng)當(dāng)廢棄的對(duì)象在超出其生存周期后繼續(xù)存在。使用__weak修飾符可以避免循環(huán)引用帆谍。

__weak表示弱引用伪朽,弱引用不能持有對(duì)象實(shí)例。

id __weak obj = [[NSObject alloc] init];//編譯器會(huì)警告

__weak修飾符還有另一個(gè)優(yōu)點(diǎn)汛蝙。在持有對(duì)象的弱引用時(shí)烈涮,若對(duì)象被廢棄朴肺,則此弱引用將失效且處于nil被賦值的狀態(tài)。

通過檢查__weak修飾的變量是否為nil可以判斷被賦值的對(duì)象是否已廢棄坚洽。

__weak只能用于iOS5和macOS10.7以上版本宇挫,在iOS4和macOS10.6及以前用__unsafe_unretained代替。

__autoreleasing修飾符

ARC下指定@autoreleasepool塊來替代NSAutoreleasePool類生成酪术、持有及廢棄這一范圍器瘪。_autoreleasing修飾變量等價(jià)于對(duì)象調(diào)用autorelease方法,即可將對(duì)象注冊(cè)到autoreleasepool中绘雁。

@autoreleasepool {
    id __autoreleasing obj = [[NSObject alloc] init];
}
  • 提問:前文提到__weak修飾的變量必須注冊(cè)到autoreleasepool中橡疼,為什么?
  • 答:因?yàn)?code>__weak修飾的變量只能持有對(duì)象的弱引用庐舟,在訪問對(duì)象的過程中欣除,該對(duì)象可能被廢棄。如果把要訪問的對(duì)象注冊(cè)到autoreleasepool中挪略,那么在@autoreleasepool塊結(jié)束之前能確保該對(duì)象存在历帚。

_autoreleasing__strong一樣,顯式使用罕見杠娱。

ARC的規(guī)則

ARC環(huán)境下編譯源代碼遵循一定規(guī)則:

  • 不能使用retain/release/retainCount/autorelease
  • 不能使用NSAllocateObject/NSDeallocateObject

ARC有效時(shí)挽牢,以上方法會(huì)導(dǎo)致編譯器報(bào)錯(cuò)。

  • 必須遵守內(nèi)存管理的方法命名規(guī)則

對(duì)象的生成摊求、持有的方法必須遵循命名規(guī)則:alloc/new/copy/mutableCopy。以init開頭的方法更嚴(yán)格:必須是實(shí)例方法且必須返回對(duì)象睹栖,返回對(duì)象的類型必須是id類型或該方法聲明類的對(duì)象類型野来。

  • 不要顯式調(diào)用dealloc

dealloc方法無需顯式調(diào)用曼氛,但C語言庫需要在deallocfree搪锣,以及刪除已注冊(cè)的通知觀察者。

  • 使用@autorelease塊代替NSAutoreleasePool

ARC有效時(shí)狗超,使用@autoreleasepool塊代替NSAutoreleasePool努咐。

  • 不能使用區(qū)域(NSZone

不管ARC是否有效渗稍,區(qū)域在現(xiàn)在運(yùn)行時(shí)系統(tǒng)中已單純地被忽略竿屹。

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

C語言的規(guī)約上沒有方法來管理結(jié)構(gòu)體成員變量的生存周期。

  • 顯式轉(zhuǎn)換“id”和“void *
/* ARC無效 */
id obj = [[NSObject alloc] init];
void *p = obj

ARC有效時(shí)需要通過__bridge來顯式轉(zhuǎn)換:

/* ARC有效 */
id obj = [[NSObject alloc] init];
void *p = (__bridge void*)obj;
id o = (__bridge id)p;

屬性和數(shù)組

  • 聲明屬性所用的關(guān)鍵詞與所有權(quán)修飾符的對(duì)應(yīng)關(guān)系:
聲明屬性的關(guān)鍵詞 所有權(quán)修飾符
assign __unsafe_unretained
copy __strong
retain __strong
strong __strong
unsafe_unretained __unsafe_unretained
weak __weak
  • 動(dòng)態(tài)數(shù)組中操作__strong修飾的變量與靜態(tài)數(shù)組有很大差異,需要自己釋放所有元素召嘶。靜態(tài)數(shù)組中哮缺,編譯器能夠根據(jù)變量的作用域自動(dòng)插入釋放賦值對(duì)象的代碼碟绑,而在動(dòng)態(tài)數(shù)組中,編譯器不能確定數(shù)組的生存周期诵冒,所以無從處理。

ARC的實(shí)現(xiàn)

__strong的實(shí)現(xiàn)

  • 自己生成并持有
{
    id __strong obj = [[NSObject alloc] init];
}
/* 編譯器的模擬代碼 */
id obj = objc_msgSend(NSObject, @selector(alloc));
objc_msgSend(obj, @selector(init));
objc_release(obj);
  • 非自己生成持有
id __strong obj = [NSMutableArray array];
/* 編譯器的模擬代碼 */
id obj = objc_msgSend(NSMutableArray, @selector(array));
objc_retainAutoreleasedReturnValue(obj);
objc_release(obj);

objc_retainAutoreleasedReturnValue函數(shù)用于持有對(duì)象,注冊(cè)到autoreleasepool中并返回铁蹈。與之對(duì)應(yīng)的函數(shù)是objc_autoreleaseReturnValue握牧。

+ (id)array {
    return [[NSMutableArray alloc] init];
}
/* 編譯器的模擬代碼 */
+ (id)array {
    id obj = objc_msgSend(NSMutableArray, @selector(alloc));
    objc_msgSend(obj, @selector(init));
    return objc_autoreleaseReturnValue(obj);
}

通過objc_retainAutoreleasedReturnValue函數(shù)和objc_autoreleaseReturnValue函數(shù)的協(xié)作,可以不將對(duì)象注冊(cè)到autoreleasepool中而直接傳遞沿腰,以達(dá)到最優(yōu)化程序運(yùn)行

__weak的實(shí)現(xiàn)

使用__weak修飾的變量颂龙,就是使用注冊(cè)到autoreleasepool中的對(duì)象。

{
    id __weak obj1 = obj;
}
/* 編譯器模擬代碼 */
id obj1;
objc_initWeak(&obj1, obj);
id tmp = objc_loadWeakRetained(&obj1);
objc_autorelease(tmp);
objc_destroyWeak(obj1);

__weak同引用計(jì)數(shù)一樣通過散列表(哈希表)實(shí)現(xiàn)措嵌,大致流程如下:

  • 1.objc_initWeak(&obj1, obj)函數(shù)初始化__weak修飾的變量,通過執(zhí)行objc_storeWeak(&obj1, obj)函數(shù)铅匹,以第一個(gè)參數(shù)(變量的地址)作為key押赊,把第二個(gè)參數(shù)(賦值對(duì)象)作為value存入哈希表。
  • 2.由于弱引用不能持有對(duì)象流礁,函數(shù)objc_loadWeakRetained(&obj1)取出所引用的對(duì)象并retain
  • 3.objc_autorelease(tmp)函數(shù)將對(duì)象注冊(cè)到autoreleasepool中。
  • 4.objc_destroyWeak(&obj1)函數(shù)釋放__weak修飾的變量萌抵,通過過程執(zhí)行objc_store(&obj1, 0)函數(shù),在weak表中查到變量地址并刪除讨永。廢棄對(duì)象調(diào)用objc_clear_deallocating函數(shù)揭糕,這個(gè)過程會(huì)將weak表記錄中__weak修飾的變量地址賦值為nil

如果大量使用__weak修飾的變量锻霎,則會(huì)消耗相應(yīng)的CPU資源著角。良策是只在需要避免循環(huán)引用時(shí)使用__weak修飾符。

__autoreleasing的實(shí)現(xiàn)

_autoreleasing修飾變量旋恼,等同于ARC無效時(shí)對(duì)象調(diào)用autorelease方法吏口。

@autoreleasepool {
    id __autoreleasing obj = [[NSObject alloc] init];
}
/* 編譯器的模擬代碼 */
id pool = objc_autoreleasePoolPush();
id obj = objc_msgSend(NSObject, @selector(alloc));
objc_msgSend(obj, @selector(init));
objc_autorelese(obj);
objc_autoreleasePoolPop();

以上為ARC篇的學(xué)習(xí)內(nèi)容。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锨侯,隨后出現(xiàn)的幾起案子嫩海,更是在濱河造成了極大的恐慌,老刑警劉巖囚痴,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叁怪,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡深滚,警方通過查閱死者的電腦和手機(jī)奕谭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痴荐,“玉大人血柳,你說我怎么就攤上這事∩祝” “怎么了难捌?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鸦难。 經(jīng)常有香客問我根吁,道長(zhǎng),這世上最難降的妖魔是什么合蔽? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任击敌,我火速辦了婚禮,結(jié)果婚禮上拴事,老公的妹妹穿的比我還像新娘沃斤。我一直安慰自己,他們只是感情好刃宵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布衡瓶。 她就那樣靜靜地躺著,像睡著了一般牲证。 火紅的嫁衣襯著肌膚如雪鞍陨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天从隆,我揣著相機(jī)與錄音,去河邊找鬼缭裆。 笑死键闺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澈驼。 我是一名探鬼主播辛燥,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了挎塌?” 一聲冷哼從身側(cè)響起徘六,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎榴都,沒想到半個(gè)月后待锈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘴高,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年竿音,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拴驮。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡春瞬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出套啤,到底是詐尸還是另有隱情宽气,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布潜沦,位于F島的核電站萄涯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏止潮。R本人自食惡果不足惜窃判,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喇闸。 院中可真熱鬧袄琳,春花似錦、人聲如沸燃乍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刻蟹。三九已至逗旁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舆瘪,已是汗流浹背片效。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留英古,地道東北人淀衣。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像召调,于是被迫代替她去往敵國和親膨桥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蛮浑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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