iOS之武功秘籍②:OC對象原理-中(內(nèi)存對齊和malloc源碼分析)

iOS之武功秘籍 文章匯總

寫在前面

iOS之武功秘籍①:OC對象原理-上(alloc & init & new)一文中講了底層對象創(chuàng)建的流程颅湘,那么本文將來探索下對象中的屬性在內(nèi)存中的排列 -- 內(nèi)存對齊 和 malloc源碼分析

本節(jié)可能用到的秘籍Demo

一涮雷、對象開辟內(nèi)存的影響因素(補(bǔ)充)

通過上一篇文章,我們已經(jīng)知道,創(chuàng)建一個(gè)對象,在經(jīng)過_class_createInstanceFromZone方法時(shí),其內(nèi)部的size = cls->instanceSize(extraBytes)能計(jì)算出創(chuàng)建這個(gè)對象所需的內(nèi)存空間大小.那么影響對象開辟內(nèi)存的因素是什么呢?

① 對于對象來說影響其內(nèi)存開辟的因素(影響對象字節(jié)對齊的因素) -- 對象的屬性(更確切的說應(yīng)該是對象的成員變量)

舉個(gè)??:
  • 當(dāng)我們的TCJPerson對象沒有其他屬性的時(shí)候,只有一個(gè)從父類NSObject繼承過來的isa時(shí),此時(shí)創(chuàng)建TCJPerson對象所需的開辟的內(nèi)存空間大小為16字節(jié).

  • 當(dāng)我們增加一個(gè)name屬性時(shí),此時(shí)的size 大小還是 16( if (size < 16) size = 16).


  • 接著我們在增加一個(gè)nickName屬性,此時(shí)需要的size大小為 32 (對象的字節(jié)對齊為16字節(jié),開辟對象的內(nèi)存大小必須是16的倍數(shù))


② 如何查看對象屬性在內(nèi)存中的顯示

測試代碼:

注:如果對象創(chuàng)建了沒去賦值屬性——它會是內(nèi)存假地址

我們應(yīng)先給對應(yīng)的屬性賦值,不然的話他們在內(nèi)存中就是假的地址.因?yàn)閮?nèi)存是連續(xù)的,如果沒去用的話,在內(nèi)存中就是野指針.

②.1 第一種方式LLDB指令 -- 查看對象屬性在內(nèi)存中的顯示

LLDB調(diào)試命令等預(yù)備知識:
  • pop:p表示"expression"——打印對象指針眉枕;而po是"expression -O"——打印對象本身

  • x 對象 表示以16進(jìn)制打印對象內(nèi)存地址(x表示memory read)

    因?yàn)閕OS是小端模式(數(shù)據(jù)的高字節(jié)保存在內(nèi)存的高地址中,而數(shù)據(jù)的低字節(jié)保存在內(nèi)存的低地址中——反過來存放數(shù)據(jù))所以要倒著讀數(shù)據(jù)

  • x/8gx 對象 表示輸出8個(gè)16進(jìn)制的8字節(jié)地址空間(x表示16進(jìn)制,8表示8個(gè)仙畦,g表示8字節(jié)為單位,等同于x/8xg 對象

根據(jù)我們的計(jì)算機(jī)基礎(chǔ)和LLDB指令,可以發(fā)現(xiàn)

  • 第一段是isa(從64位開始,isa需要進(jìn)行一個(gè)位運(yùn)算 & ISA_MASK 操作,而x86環(huán)境下,ISA_MASK的值為0x0000000ffffffff8ULL)
  • 第二段中0x0000001218 -- 對應(yīng)age,而62替劈、61分別是baASCII編碼
  • 第三段中po出來是TCJ--對應(yīng)name
  • 第四段中po出來是CJ-- 對應(yīng)nickName
  • 第五段是po出來是185 -- 對應(yīng)height
查看控制臺輸出:
去掉聲明屬性查看控制臺輸出:

TCJPerson類中不聲明任何屬性:

提出問題

Q1:為什么成員變量的順序和我們聲明屬性的順序不同得滤?!

Q2:sizeof陨献、class_getInstanceSize、malloc_size分別是什么懂更?
后面講解....
Q3:不是說對象最少為16字節(jié)眨业,為什么class_getInstanceSize還能輸出8字節(jié)?
后面講解...

②.2 第二種方式:實(shí)時(shí)查看內(nèi)存狀況Debug->Debug Workflow->View Memory(shift + Command +M)

一般不推薦用第二種方式.

二沮协、字節(jié)對齊

① sizeof龄捡、class_getInstanceSize、malloc_size

  • sizeof():是一個(gè)運(yùn)算符,不是函數(shù).傳入數(shù)據(jù)類型,輸出內(nèi)存大小,在編譯時(shí)確定.只與數(shù)據(jù)類型相關(guān)慷暂,與具體數(shù)值無關(guān)聘殖。(如:bool 2字節(jié),int 4字節(jié),對象(指針)8字節(jié))
  • class_getInstanceSize:依賴于<objc/runtime.h>,是runtime提供的api,用于獲取類的實(shí)例對象所占用的內(nèi)存大小行瑞,并返回具體的字節(jié)數(shù)奸腺,其本質(zhì)就是獲取實(shí)例對象中成員變量的內(nèi)存大小(8字節(jié)對齊)
  • malloc_size:依賴于<malloc/malloc.h>,返回系統(tǒng)實(shí)際分配的內(nèi)存大小(16字節(jié)對齊)

前面的打印也就得以驗(yàn)證.

在來總結(jié)一波:

  • sizeof:計(jì)算類型占用的內(nèi)存大小血久,其中可以放 基本數(shù)據(jù)類型突照、對象指針

    • 對于類似于int這樣的基本數(shù)據(jù)而言氧吐,sizeof獲取的就是數(shù)據(jù)類型占用的內(nèi)存大小讹蘑,不同的數(shù)據(jù)類型所占用的內(nèi)存大小是不一樣的
    • 而對于類似于NSObject定義的實(shí)例對象而言,其對象類型的本質(zhì)就是一個(gè)結(jié)構(gòu)體(即 struct objc_object)的指針副砍,所以sizeof(objc)打印的是對象objc的指針大小衔肢,我們知道一個(gè)指針的內(nèi)存大小是8字節(jié),所以sizeof(objc) 打印是 8.注意:這里的8字節(jié)與isa指針一點(diǎn)關(guān)系都沒有;眙帷=侵琛!
    • 對于指針而言,sizeof打印的就是8邦尊,因?yàn)橐粋€(gè)指針的內(nèi)存大小是8字節(jié).
  • class_getInstanceSize:計(jì)算對象實(shí)際占用的內(nèi)存大小背桐,這個(gè)需要依據(jù)類的屬性而變化,如果自定義類沒有自定義屬性蝉揍,僅僅只是繼承自NSObject链峭,則類的實(shí)例對象實(shí)際占用的內(nèi)存大小是8,遵循8字節(jié)對齊.

  • malloc_size:計(jì)算對象實(shí)際分配的內(nèi)存大小又沾,這個(gè)是由系統(tǒng)完成的.可以從上面的打印結(jié)果看出弊仪,實(shí)際分配的和實(shí)際占用的內(nèi)存大小并不相等.

② 對象的內(nèi)存對齊

我們知道就對象整體而言,蘋果系統(tǒng)采用16字節(jié)對齊開辟內(nèi)存大小杖刷,提高系統(tǒng)存取性能励饵。

那么對于對象內(nèi)部呢?

  • 對象的本質(zhì)是結(jié)構(gòu)體,這個(gè)在后續(xù)篇章中我們會詳細(xì)講解.所以研究對象內(nèi)部的內(nèi)存滑燃,就是研究結(jié)構(gòu)體的內(nèi)存布局.
  • 內(nèi)存對齊目的:最大程度提高資源利用率.

③ 結(jié)構(gòu)體內(nèi)存對齊

搞個(gè)??瞧瞧:

輸出結(jié)果: CJStruct1-24 CJStruct2-16 CJStruct3-32 CJStruct4-24 .

從打印結(jié)果我們可以看出一個(gè)問題役听,兩個(gè)結(jié)構(gòu)體乍一看,沒什么區(qū)別表窘,其中定義的變量 和 變量類型都是一致的典予,唯一的區(qū)別只是在于定義變量的順序不一致,那為什么他們做占用的內(nèi)存大小不相等呢乐严?結(jié)構(gòu)體內(nèi)部的元素排序影響內(nèi)存大小.其實(shí)這就是iOS中的內(nèi)存字節(jié)對齊現(xiàn)象.

結(jié)構(gòu)體內(nèi)存對齊規(guī)則
每個(gè)特定平臺上的編譯器都有自己的默認(rèn)“對齊系數(shù)”(也叫對齊模數(shù)).程序員可以通過預(yù)編譯命令#pragma pack(n)瘤袖,n=1,2,4,8,16來改變這一系數(shù),其中的n就是你要指定的“對齊系數(shù)”.在iOS中麦备,Xcode默認(rèn)為#pragma pack(8)孽椰,即8字節(jié)對齊

注意:這里的8字節(jié)對齊是結(jié)構(gòu)體內(nèi)部對齊規(guī)則,對象在系統(tǒng)中對外實(shí)際分配的空間是遵循16字節(jié)對齊原則凛篙。

【三條內(nèi)存對齊規(guī)則】:

  • 數(shù)據(jù)成員的對齊規(guī)則可以理解為min(m, n)的公式, 其中m表示當(dāng)前成員的開始位置, n表示當(dāng)前成員所需位數(shù).如果滿足條件 m 整除 n (即 m % n == 0), nm 位置開始存儲, 反之繼續(xù)檢查 m+1 能否整除 n, 直到可以整除, 從而就確定了當(dāng)前成員的開始位置.
  • 數(shù)據(jù)成員為結(jié)構(gòu)體:當(dāng)結(jié)構(gòu)體嵌套了結(jié)構(gòu)體時(shí)黍匾,作為數(shù)據(jù)成員的結(jié)構(gòu)體的自身長度作為外部結(jié)構(gòu)體的最大成員的內(nèi)存大小(即在確定復(fù)合類型成員的偏移位置時(shí)則是將復(fù)合類型作為整體看待),且結(jié)構(gòu)體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開始存儲.比如結(jié)構(gòu)體a嵌套結(jié)構(gòu)體b呛梆,b中有char锐涯、int、double等填物,那b應(yīng)該從8的整數(shù)倍開始存儲.
  • 最后結(jié)構(gòu)體的內(nèi)存大小必須是結(jié)構(gòu)體中最大成員內(nèi)存大小的整數(shù)倍纹腌,不足的需要補(bǔ)齊.

iOS基礎(chǔ)數(shù)據(jù)類型占用的字節(jié)數(shù)表

利用結(jié)構(gòu)體對齊規(guī)則來分析前面的??

結(jié)構(gòu)體CJStruct1內(nèi)存大小計(jì)算:

  • 變量a:占8個(gè)字節(jié),從0開始滞磺,此時(shí)min(0升薯,8),即 0-7 存儲 a
  • 變量b:占1個(gè)字節(jié)击困,從8開始涎劈,此時(shí)min(8广凸,1),8能整除1蛛枚,谅海,即 8 存儲 b
  • 變量c:占4個(gè)字節(jié),從9開始蹦浦,此時(shí)min(9扭吁,4),9不能整除4盲镶,繼續(xù)往后移動侥袜,直到min(12,4)徒河,從12開始即 12-15 存儲 c
  • 變量d:占2個(gè)字節(jié)系馆,從16開始,此時(shí)min(16, 2)顽照,16可以整除2,即16-17 存儲 d
    因此CJStruct1的需要的內(nèi)存大小為 18 字節(jié)闽寡,而CJStruct1中最大變量的字節(jié)數(shù)為8代兵,所以 CJStruct1 實(shí)際的內(nèi)存大小必須是 8 的整數(shù)倍,18向上取整到24爷狈,主要是因?yàn)?4是8的整數(shù)倍植影,所以 sizeof(CJStruct1) 的結(jié)果是 24.

結(jié)構(gòu)體CJStruct2 內(nèi)存大小計(jì)算:

  • 變量a:占8個(gè)字節(jié),從0開始涎永,此時(shí)min(0思币,8),即 0-7 存儲 b
  • 變量b:占4個(gè)字節(jié)羡微,從8開始谷饿,此時(shí)min(8,4)妈倔,8可以整除4博投,即 8-11 存儲 c
  • 變量c:占1個(gè)字節(jié),從12開始盯蝴,此時(shí)min(12, 1)毅哗,12可以整除1,即12 存儲 d
  • 變量d:占2個(gè)字節(jié)捧挺,從13開始虑绵,此時(shí)min(13,2)闽烙,13不能整除2翅睛,繼續(xù)往后移動,直到min(14,2)宏所,從14開始即 14-15 存儲 c
    因此CJStruct2的需要的內(nèi)存大小為 16字節(jié)酥艳,而CJStruct2中最大變量的字節(jié)數(shù)為8,所以 CJStruct2 實(shí)際的內(nèi)存大小必須是 8 的整數(shù)倍爬骤,而 16 正好是 8 的整數(shù)倍充石,所以 sizeof(CJStruct2) 的結(jié)果是 16.

結(jié)構(gòu)體CJStruct3內(nèi)存大小計(jì)算:

  • 變量e:占4個(gè)字節(jié),從0開始霞玄,此時(shí)min(0骤铃,4),即 0-3 存儲 e
  • 結(jié)構(gòu)體成員CJStruct1CJStruct1是一個(gè)結(jié)構(gòu)體,占24字節(jié).根據(jù)內(nèi)存對齊原則二坷剧,結(jié)構(gòu)體成員要從其內(nèi)部最大成員大小的整數(shù)倍開始存儲惰爬,而CJStruct1中最大的成員大小為8,所以CJStruct1要從8的整數(shù)倍開始惫企,當(dāng)前是從4開始撕瞧,所以不符合要求,需要往后移動到8狞尔,8是8的整數(shù)倍丛版,符合內(nèi)存對齊原則,所以 8-31 存儲 CJStruct1.
    因此CJStruct3需要的內(nèi)存大小為 32 字節(jié)偏序,而CJStruct3 中最大變量為CJStruct1, 其最大成員內(nèi)存字節(jié)數(shù)為8页畦,根據(jù)內(nèi)存對齊原則,所以 CJStruct3 實(shí)際的內(nèi)存大小必須是 8 的整數(shù)倍研儒,32正好是8的整數(shù)倍豫缨,所以 sizeof(CJStruct3) 的結(jié)果是 32.

結(jié)構(gòu)體CJStruct4內(nèi)存大小計(jì)算:

  • 變量e:占8個(gè)字節(jié),從0開始端朵,此時(shí)min(0好芭,8),即 0-7 存儲 e
  • 結(jié)構(gòu)體成員CJStruct2CJStruct2是一個(gè)結(jié)構(gòu)體,占16字節(jié).根據(jù)內(nèi)存對齊原則二逸月,結(jié)構(gòu)體成員要從其內(nèi)部最大成員大小的整數(shù)倍開始存儲栓撞,而CJStruct2中最大的成員大小為8,所以CJStruct2要從8的整數(shù)倍開始碗硬,當(dāng)前是從8開始瓤湘,符合要求,符合內(nèi)存對齊原則恩尾,所以 8-23 存儲 CJStruct2.
    因此CJStruct4需要的內(nèi)存大小為 24 字節(jié)弛说,而CJStruct4 中最大變量為CJStruct2, 其最大成員內(nèi)存字節(jié)數(shù)為8,根據(jù)內(nèi)存對齊原則翰意,所以 CJStruct4 實(shí)際的內(nèi)存大小必須是 8 的整數(shù)倍木人,24正好是8的整數(shù)倍信柿,所以 sizeof(CJStruct4) 的結(jié)果是 24.

④ 內(nèi)存優(yōu)化(屬性重排)

如果按照對象默認(rèn)聲明的屬性順序進(jìn)行內(nèi)存分配,在進(jìn)行屬性的8字節(jié)對齊時(shí)會浪費(fèi)大量的內(nèi)存空間醒第,所以這里系統(tǒng)會把對象的屬性重新排列渔嚷,以此來最大化利用我們的內(nèi)存空間

驗(yàn)證①:
CJStruct1CJStruct2而言,他們的成員屬性一樣,只是他們之間的屬性排列位置不同,他們分別占用不同的內(nèi)存.

驗(yàn)證②:
就前面 -- 如何查看對象屬性在內(nèi)存中的顯示 中的例子也驗(yàn)證了這一點(diǎn).
我們聲明TCJPerson的屬性的順序是:isa(繼承NSObject) -> name(NSString) -> nickName(NSString) ->age(int) -> height(long) -> c1(char) -> c2(char);

而實(shí)際分配內(nèi)存時(shí)的屬性順序是:isa(繼承NSObject) ->age(int) -> c2(char) -> c1(char) -> nickName(NSString) -> name(NSString)-> height(long),并且將age 和 c1 及 c2 存放在了一個(gè)塊區(qū). 這就是蘋果的內(nèi)存優(yōu)化的體現(xiàn).

⑤小彩蛋

  • 對于對象之間,系統(tǒng)面對的對象太多稠曼,系統(tǒng)為了防止容錯(cuò)形病,采用的是16字節(jié)對齊的內(nèi)存,給對象留足夠間距,避免越界訪問(所以malloc_size讀取的都是16的倍數(shù))
  • 但為了避免浪費(fèi)太多內(nèi)存空間,系統(tǒng)會在每個(gè)對象內(nèi)部進(jìn)行屬性重排霞幅,并使用8字節(jié)對齊漠吻,使單個(gè)對象占用的資源盡可能小.(所以class_getInstanceSize讀取的都是8的倍數(shù))

三、malloc源碼輔助分析

通過上一篇文章,我們已經(jīng)知道,創(chuàng)建一個(gè)對象,在經(jīng)過_class_createInstanceFromZone方法時(shí),其內(nèi)部的obj = (id)calloc(1, size)方法是根據(jù)計(jì)算好的空間大小size(如size = 40),去系統(tǒng)申請空間,并返回地址指針的.
我們發(fā)現(xiàn)點(diǎn)擊calloc進(jìn)入內(nèi)部司恳,只能看到calloc聲明.無法再繼續(xù)前進(jìn)了

我們可以看到calloc的聲明是在malloc源碼中.

打開我為你們準(zhǔn)備好的可編譯的malloc源碼.

① calloc

libmalloc源碼中新建target途乃,按照objc源碼中的調(diào)用方式操作:

② malloc_zone_calloc

之后進(jìn)入calloc流程,進(jìn)行具體的內(nèi)存開辟扔傅,在使用calloc申請內(nèi)存的過程中耍共,首先調(diào)用malloc_zone_calloc方法


根據(jù)return ptr可知ptr是重點(diǎn),但是ptr = zone->calloc(zone, num_items, size);跟進(jìn)去會看到讓人一串摸不到頭腦的代碼,而且到此源碼還無法繼續(xù)跟進(jìn)了:

③ default_zone_calloc

那么重點(diǎn)來了A匀;帷!想要繼續(xù)跟進(jìn)源碼邢享,可以通過以下方法:

方法一: —— 分析zone

已知zonemalloc_zone_t類型的,在第二步中retval = malloc_zone_calloc(default_zone, num_items, size);中傳遞的第一個(gè)參數(shù)zone又是default_zone淡诗,跟蹤進(jìn)去會發(fā)現(xiàn)它是一個(gè)靜態(tài)變量

static malloc_zone_t *default_zone = &virtual_default_zone.malloc_zone;
static virtual_default_zone_t virtual_default_zone
__attribute__((section("__DATA,__v_zone")))
__attribute__((aligned(PAGE_MAX_SIZE))) = {
    NULL,
    NULL,
    default_zone_size,
    default_zone_malloc,
    default_zone_calloc,
    default_zone_valloc,
    default_zone_free,
    default_zone_realloc,
    default_zone_destroy,
    DEFAULT_MALLOC_ZONE_STRING,
    default_zone_batch_malloc,
    default_zone_batch_free,
    &default_zone_introspect,
    10,
    default_zone_memalign,
    default_zone_free_definite_size,
    default_zone_pressure_relief,
    default_zone_malloc_claimed_address,
};

初步推測zone->alloc是default_zone_calloc

方法二: —— 控制臺打印

有時(shí)候打印也是閱讀源碼的一種方法——由打印可知實(shí)際調(diào)用default_zone_calloc

方法三: —— 按住control + step into骇塘,進(jìn)入calloc的源碼

加上圖中的斷點(diǎn),來到斷點(diǎn)后:按住control + step into同樣也會來到:

這其中有兩個(gè)非常重要的操作:

  • 創(chuàng)建真正的zone,即runtime_default_zone方法
  • 使用真正的zone進(jìn)行calloc

④ nano_calloc

繼續(xù)打印zone->calloc,得到提示nano_calloc:

malloc的源碼中搜索nano_calloc韩容,于nano_malloc.c文件中找到該方法款违,其中的核心代碼_nano_malloc_check_clear,進(jìn)行內(nèi)存申請群凶,并且返回一個(gè)成熟的指針ptr.

⑤ _nano_malloc_check_clear

分析:這個(gè)方法中有三個(gè)return和一句注釋/* FALLTHROUGH to helper zone */——進(jìn)入輔助區(qū)域插爹,即正常情況下走if判斷(如果要開辟的空間小于 NANO_MAX_SIZE 則進(jìn)行nanozone_t的malloc)NANO_MAX_SIZE=256

⑥ segregated_size_to_fit

進(jìn)入_nano_malloc_check_clear特姐,此時(shí)此刻看到這么長的一段代碼也不用慌張膘格,if-else只走其一.再仔細(xì)想想嗦玖,我們是帶著目的來看源碼的——malloc_size中的48是怎么來的.這里有多個(gè)size_t類璃搜,斷點(diǎn)調(diào)試看了下的size是我們傳進(jìn)來的40郁油,而slot_bytes剛好是我們的目標(biāo)48蔫仙,那我們就來看下40->48是怎么來的,將error的異常判斷分支折疊起來,查看主流程:

  • 其中segregated_next_block 就是指針內(nèi)存開辟算法类茂,目的是找到合適的內(nèi)存并返回(不斷遞歸去尋找合適的內(nèi)存空間)
  • slot_bytes是加密算法的鹽(其目的是為了讓加密算法更加安全冗疮,本質(zhì)就是一串自定義的數(shù)字)

⑦ 16字節(jié)對齊

分析:size 是 40够坐,在經(jīng)過 (40 + 16 - 1) >> 4 << 4 操作后寸宵,結(jié)果為48崖面,也就是16的整數(shù)倍——即16字節(jié)對齊.

寫在后面

總結(jié):

  • 對象的屬性是按照8字節(jié)進(jìn)行對齊的
  • 對象本身則是按照16字節(jié)進(jìn)行對齊的
    • 因?yàn)閮?nèi)存是連續(xù)的,通過 16 字節(jié)對齊規(guī)避了風(fēng)險(xiǎn)和容錯(cuò)梯影,有效的防止了訪問溢出
    • 同時(shí)巫员,也提高了尋址訪問效率,也就是通常我們所說的空間換時(shí)間
  • 和諧學(xué)習(xí),不急不躁.我還是我,顏色不一樣的煙火.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甲棍,一起剝皮案震驚了整個(gè)濱河市简识,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌救军,老刑警劉巖财异,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異唱遭,居然都是意外死亡戳寸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門拷泽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疫鹊,“玉大人,你說我怎么就攤上這事司致〔疬海” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵脂矫,是天一觀的道長枣耀。 經(jīng)常有香客問我,道長庭再,這世上最難降的妖魔是什么捞奕? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮拄轻,結(jié)果婚禮上颅围,老公的妹妹穿的比我還像新娘。我一直安慰自己恨搓,他們只是感情好院促,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斧抱,像睡著了一般常拓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夺姑,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天墩邀,我揣著相機(jī)與錄音,去河邊找鬼盏浙。 笑死眉睹,一個(gè)胖子當(dāng)著我的面吹牛荔茬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竹海,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼慕蔚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了斋配?” 一聲冷哼從身側(cè)響起孔飒,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎艰争,沒想到半個(gè)月后坏瞄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡甩卓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年鸠匀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逾柿。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缀棍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出机错,到底是詐尸還是另有隱情爬范,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布弱匪,位于F島的核電站青瀑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏萧诫。R本人自食惡果不足惜狱窘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望财搁。 院中可真熱鬧,春花似錦躬络、人聲如沸尖奔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽提茁。三九已至,卻和暖如春馁菜,著一層夾襖步出監(jiān)牢的瞬間茴扁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工汪疮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留峭火,地道東北人毁习。 一個(gè)月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像卖丸,于是被迫代替她去往敵國和親纺且。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

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