匯編窺探Swift底層(五):字符串

窺探字符串的內(nèi)存

    1. 首先 塘秦,我們定義一個(gè)短的字符串筷狼,如下所示,通過MemoryLayout打印恃鞋,我們知道了str1變量占用了16個(gè)字節(jié)崖媚,那么這16個(gè)字節(jié)究竟存儲(chǔ)了什么呢 ,我們通過匯編來看一下
var str1 = "0123456789"
print(MemoryLayout.stride(ofValue: str1)) 打印出來是16個(gè)字節(jié)恤浪,也就是說str1占用了16字節(jié)
    1. 為了防止干擾畅哑,我們把打印的代碼注釋掉,只留下var str1 = "0123456789"资锰,以下就是這句代碼的匯編代碼
TestSwift`main:
    0x100001390 <+0>:  pushq  %rbp
    0x100001391 <+1>:  movq   %rsp, %rbp
    0x100001394 <+4>:  subq   $0x10, %rsp
->  0x100001398 <+8>:  leaq   0x4361(%rip), %rax        ; "0123456789"
    0x10000139f <+15>: movl   %edi, -0x4(%rbp)
    0x1000013a2 <+18>: movq   %rax, %rdi
    0x1000013a5 <+21>: movl   $0xa, %eax
    0x1000013aa <+26>: movq   %rsi, -0x10(%rbp)
    0x1000013ae <+30>: movq   %rax, %rsi
    0x1000013b1 <+33>: movl   $0x1, %edx
    0x1000013b6 <+38>: callq  0x100005402               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
    0x1000013bb <+43>: xorl   %ecx, %ecx
    0x1000013bd <+45>: movq   %rax, 0x5e24(%rip)        ; TestSwift.str1 : Swift.String
    0x1000013c4 <+52>: movq   %rdx, 0x5e25(%rip)        ; TestSwift.str1 : Swift.String + 8
    0x1000013cb <+59>: movl   %ecx, %eax
    0x1000013cd <+61>: addq   $0x10, %rsp
    0x1000013d1 <+65>: popq   %rbp
    0x1000013d2 <+66>: retq   

    1. 我們重點(diǎn)觀察一下下面兩句匯編敢课,通過注釋和操作數(shù)q(q代表操作8個(gè)字節(jié)的空間),就可以看出來第一句是操作了str1變量的前8個(gè)字節(jié)绷杜,第二句操作了str1變量的后8個(gè)字節(jié)
0x1000013bd <+45>: movq   %rax, 0x5e24(%rip)        ; TestSwift.str1 : Swift.String
0x1000013c4 <+52>: movq   %rdx, 0x5e25(%rip)        ; TestSwift.str1 : Swift.String + 8
    1. 0x5e24(%rip)的意思就是將rip寄存器的值與0x5e24相加 直秆,我們知道rip寄存器存儲(chǔ)著下一條指令的地址,也就是0x1000013c4鞭盟,與0x5e24相加圾结,就是0x1000071E8,通過LLDB命令x/2xg齿诉,打印出從0x1000071E8地址開始的16個(gè)字節(jié)的數(shù)據(jù)筝野,來進(jìn)行觀察晌姚,如下所示
(lldb) x/2xg 0x1000071E8
0x1000071e8: 0x3736353433323130 0xea00000000003938

上面是小端模式讀取的,不好看歇竟,現(xiàn)在用另一種模式讀取挥唠,就很容易看出來
(lldb) x 0x1000071E8
0x1000071e8: 30 31 32 33 34 35 36 37 38 39 00 00 00 00 00 ea  0123456789......
0x1000071f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

    1. 我們發(fā)現(xiàn)str1變量中存儲(chǔ)的數(shù)據(jù)就是字符串"0123456789"ASCII值的十六進(jìn)制,也就是說短的字符串焕议,數(shù)據(jù)直接會(huì)存放在變量的內(nèi)存里面(非常類似OC中的tagger pointer)宝磨。
    1. 我們逐漸加長(zhǎng)字符串并且一一查看內(nèi)存,如下所示盅安,就可以看出來唤锉,當(dāng)字符串的長(zhǎng)度小于16時(shí),隨著字符串長(zhǎng)度的逐漸增加别瞭,最后一個(gè)字節(jié)存放著0xe不變窿祥,0xa逐漸增大到了0xf,也就說0xe很有可能代表字符串的類型蝙寨,而0xa肯定就是字符串的長(zhǎng)度晒衩;當(dāng)字符串的長(zhǎng)度大于等于16時(shí),str1變量的內(nèi)存突然就發(fā)生了變化籽慢,那么此時(shí)字符串是怎么存儲(chǔ)的呢浸遗?
var str1 = "0123456789"時(shí),      str1的內(nèi)存是:0x3736353433323130 0xea00000000003938

var str1 = "0123456789A"時(shí)箱亿,     str1的內(nèi)存是:0x3736353433323130 0xeb00000000413938

var str1 = "0123456789AB"時(shí),    str1的內(nèi)存是:0x3736353433323130 0xec00000042413938

var str1 = "0123456789ABC"時(shí)弃秆,   str1的內(nèi)存是:0x3736353433323130 0xed00004342413938

var str1 = "0123456789ABCD"時(shí)届惋,  str1的內(nèi)存是:0x3736353433323130 0xee00444342413938

var str1 = "0123456789ABCDE"時(shí), str1的內(nèi)存是:0x3736353433323130 0xef45444342413938

var str1 = "0123456789ABCDEF"時(shí)菠赚,str1的內(nèi)存是:0xd000000000000010 0x80000001000056d0
    1. 我們來分析一下var str1 = "0123456789ABCDEF"的匯編代碼脑豹,窺探一下字符串是怎么存儲(chǔ)的,下面就是這句代碼的匯編代碼
TestSwift`main:
    0x100001380 <+0>:  pushq  %rbp
    0x100001381 <+1>:  movq   %rsp, %rbp
    0x100001384 <+4>:  subq   $0x10, %rsp
->  0x100001388 <+8>:  leaq   0x4361(%rip), %rax        ; "0123456789ABCDEF"
    0x10000138f <+15>: movl   %edi, -0x4(%rbp)
    0x100001392 <+18>: movq   %rax, %rdi
    0x100001395 <+21>: movl   $0x10, %eax
    0x10000139a <+26>: movq   %rsi, -0x10(%rbp)
    0x10000139e <+30>: movq   %rax, %rsi
    0x1000013a1 <+33>: movl   $0x1, %edx
    0x1000013a6 <+38>: callq  0x1000053f2               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
    0x1000013ab <+43>: xorl   %ecx, %ecx
    0x1000013ad <+45>: movq   %rax, 0x5e34(%rip)        ; TestSwift.str1 : Swift.String
    0x1000013b4 <+52>: movq   %rdx, 0x5e35(%rip)        ; TestSwift.str1 : Swift.String + 8
    0x1000013bb <+59>: movl   %ecx, %eax
    0x1000013bd <+61>: addq   $0x10, %rsp
    0x1000013c1 <+65>: popq   %rbp
    0x1000013c2 <+66>: retq   

    1. 重點(diǎn)觀察這幾句匯編衡查,我們來一句一句分析一下瘩欺,如下所示
    leaq指令是直接賦值地址,從注釋可以看出來是把"0123456789ABCDEF"的真實(shí)地址給了rax寄存器
    通過rip+0x4361拌牲,可以算出字符串的真實(shí)地址是:0x1000056F0
    0x100001388 <+8>:  leaq   0x4361(%rip), %rax        ; "0123456789ABCDEF"

    又把rax寄存器的值給了rdi寄存器俱饿,也就是說rdi寄存器里存放著字符串的真實(shí)地址
    0x100001392 <+18>: movq   %rax, %rdi

    把0x10給了eax寄存器,eax寄存器就是rax寄存器塌忽,也就是說rax寄存器里存儲(chǔ)著字符串的長(zhǎng)度(十六進(jìn)制0x10就是十進(jìn)制的16)
    0x100001395 <+21>: movl   $0x10, %eax

    又把rax寄存器的值給了rsi寄存器拍埠,也就是說rsi寄存器里的值就是字符串的長(zhǎng)度
    0x10000139e <+30>: movq   %rax, %rsi

    調(diào)用了函數(shù)String.init(),把rdi寄存器和rsi寄存器作為了參數(shù)土居,也就說把字符串的真實(shí)地址和字符串長(zhǎng)度作為參數(shù)枣购,調(diào)用了String.init()
    0x1000013a6 <+38>: callq  0x1000053f2               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String

    把rax寄存器的值給了str1變量的前8個(gè)字節(jié)
    0x1000013ad <+45>: movq   %rax, 0x5e34(%rip)        ; TestSwift.str1 : Swift.String

    把rdx寄存器的值給了str1變量的后8個(gè)字節(jié)
    0x1000013b4 <+52>: movq   %rdx, 0x5e35(%rip)        ; TestSwift.str1 : Swift.String + 8
 
    1. 從上面分析可以看出來嬉探,rdi寄存器存放著字符串的真實(shí)地址,rsi寄存器存放著字符串的長(zhǎng)度棉圈,然后又把這兩個(gè)作為參數(shù)涩堤,調(diào)用了String.init()函數(shù),最后函數(shù)的把返回值存在了rax寄存器rdx寄存器中分瘾,又分別放到了str1變量的前8個(gè)字節(jié)和后8個(gè)字節(jié)中胎围,那么我們?cè)賮矸治鲆幌?code>String.init()函數(shù)內(nèi)部究竟做了什么,我們來看一下String.init()函數(shù)的匯編代碼:
libswiftCore.dylib`Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String:
->  0x7fff722e9c40 <+0>:   pushq  %rbp
    0x7fff722e9c41 <+1>:   movq   %rsp, %rbp
    0x7fff722e9c44 <+4>:   pushq  %r14
    0x7fff722e9c46 <+6>:   pushq  %rbx
    0x7fff722e9c47 <+7>:   subq   $0x10, %rsp
    0x7fff722e9c4b <+11>:  testq  %rsi, %rsi
    0x7fff722e9c4e <+14>:  js     0x7fff722e9e31            ; <+497>
    0x7fff722e9c54 <+20>:  movl   %edx, %eax
    0x7fff722e9c56 <+22>:  movabsq $-0x2000000000000000, %rdx ; imm = 0xE000000000000000 
    0x7fff722e9c60 <+32>:  testq  %rsi, %rsi
    0x7fff722e9c63 <+35>:  je     0x7fff722e9ca4            ; <+100>
    0x7fff722e9c65 <+37>:  cmpq   $0xf, %rsi
    0x7fff722e9c69 <+41>:  jle    0x7fff722e9cab            ; <+107>
    0x7fff722e9c6b <+43>:  movabsq $-0x4000000000000000, %rcx ; imm = 0xC000000000000000 
    0x7fff722e9c75 <+53>:  orq    %rsi, %rcx
    0x7fff722e9c78 <+56>:  testb  $0x1, %al
    0x7fff722e9c7a <+58>:  cmoveq %rsi, %rcx
    0x7fff722e9c7e <+62>:  movabsq $0x1000000000000000, %rax ; imm = 0x1000000000000000 
    0x7fff722e9c88 <+72>:  orq    %rcx, %rax
    0x7fff722e9c8b <+75>:  movabsq $0x7fffffffffffffe0, %rdx ; imm = 0x7FFFFFFFFFFFFFE0 
    0x7fff722e9c95 <+85>:  addq   %rdx, %rdi
    0x7fff722e9c98 <+88>:  addq   $0x20, %rdx
    1. 我們重點(diǎn)看下面三句匯編芹敌,在String.init()函數(shù)內(nèi)部痊远,它比較了0xfrsi寄存器值的大小,前面說過rsi寄存器中存放著字符串的長(zhǎng)度氏捞,也就是比較了0xf與字符串的長(zhǎng)度碧聪;又把rdx寄存器的值變成了字符串的真實(shí)地址+$0x7fffffffffffffe0,從上面的分析我們知道rdx寄存器的值最后又給了str1變量的后8個(gè)字節(jié)液茎,也就是說現(xiàn)在str1變量的后8個(gè)字節(jié)存放的是字符串的真實(shí)地址+$0x7fffffffffffffe0
    比較0xf與rsi寄存器值的大小逞姿,前面說過rsi寄存器中存放著字符串的長(zhǎng)度
    0x7fff722e9c65 <+37>:  cmpq   $0xf, %rsi

    將立即數(shù)$0x7fffffffffffffe0放到rdx寄存器中
    0x7fff722e9c8b <+75>:  movabsq $0x7fffffffffffffe0, %rdx ; imm = 0x7FFFFFFFFFFFFFE0 

    將rdx寄存器中的值與rdi寄存器相加,并且放到rdx寄存器中捆等,前面說過rdi寄存器放著字符串的真實(shí)地址  
    所以現(xiàn)在rdx寄存器中放著字符串的真實(shí)地址+$0x7fffffffffffffe0
    0x7fff722e9c95 <+85>:  addq   %rdx, %rdi
    1. 通過以下兩種方式都可以算出來字符串的真實(shí)地址是0x1000056F0滞造,那么這個(gè)地址究竟指向內(nèi)存空間的哪里呢,我們通過MacOView工具來查看一下這個(gè)地址
   通過rip+0x4361栋烤,可以算出字符串的真實(shí)地址是:0x1000056F0
   0x100001388 <+8>:  leaq   0x4361(%rip), %rax        ; "0123456789ABCDEF"

   也可以通過str1后8個(gè)字節(jié)的數(shù)據(jù)  - 0x7fffffffffffffe0 算出來谒养,字符串的真實(shí)地址是0x1000056F0
   var str1 = "0123456789ABCDEF"時(shí),str1的內(nèi)存是:0xd000000000000010 0x80000001000056d0
    1. MacOView中的地址是虛擬地址明郭,需要加上0x1000000才是內(nèi)存中的真實(shí)地址买窟,也就是字符串的真實(shí)地址0x1000056F0,減去0x1000000薯定,算出來的0x56F0才是在MacOView中的虛擬地址始绍,從這個(gè)0x56F0地址存放的位置,從下圖可以看出话侄,字符串在_TEXT,_cstring中亏推,也就是常量區(qū),所以得出結(jié)論:當(dāng)字符串的長(zhǎng)度大于等于16時(shí)年堆,字符串會(huì)存儲(chǔ)在常量區(qū)吞杭。
      0x56F0的位置
    1. 其實(shí)無論字符串長(zhǎng)短,初始化時(shí)的字符串都會(huì)在常量區(qū)嘀韧,當(dāng)字符串長(zhǎng)度小于16時(shí)篇亭,會(huì)把常量區(qū)的字符串直接放到變量的內(nèi)存中;當(dāng)字符串長(zhǎng)度大于等于16時(shí)锄贷,會(huì)把常量區(qū)的地址加上某個(gè)立即數(shù)译蒂,然后放在變量的后8個(gè)字節(jié)中曼月。
    1. 我們知道當(dāng)程序運(yùn)行時(shí),常量區(qū)的值就不能更改了柔昼,那么當(dāng)我們拼接字符串時(shí)哑芹,字符串又是如何存儲(chǔ)的呢?來看看下面的代碼
var str1 = "0123456789ABCDEF"
str1.append("G")
    1. 這兩句代碼的匯編是這樣的 :
TestSwift`main:
    0x100001300 <+0>:   pushq  %rbp
    0x100001301 <+1>:   movq   %rsp, %rbp
    0x100001304 <+4>:   pushq  %r13
    0x100001306 <+6>:   subq   $0x38, %rsp
->  0x10000130a <+10>:  leaq   0x43df(%rip), %rax        ; "0123456789ABCDEF"
    0x100001311 <+17>:  movl   %edi, -0x24(%rbp)
    0x100001314 <+20>:  movq   %rax, %rdi
    0x100001317 <+23>:  movl   $0x10, %eax
    0x10000131c <+28>:  movq   %rsi, -0x30(%rbp)
    0x100001320 <+32>:  movq   %rax, %rsi
    0x100001323 <+35>:  movl   $0x1, %edx
    0x100001328 <+40>:  callq  0x1000053d2               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
    0x10000132d <+45>:  movq   %rax, 0x5ec4(%rip)        ; TestSwift.str1 : Swift.String
    0x100001334 <+52>:  movq   %rdx, 0x5ec5(%rip)        ; TestSwift.str1 : Swift.String + 8
    0x10000133b <+59>:  leaq   0x43bf(%rip), %rdi        ; "'G'"
    0x100001342 <+66>:  movl   $0x1, %esi
    0x100001347 <+71>:  movl   $0x1, %edx
    0x10000134c <+76>:  callq  0x1000053d2               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
    0x100001351 <+81>:  leaq   0x5ea0(%rip), %rsi        ; TestEnumMemory.str1 : Swift.String
    0x100001358 <+88>:  xorl   %ecx, %ecx
    0x10000135a <+90>:  movq   %rsi, %rdi
    0x10000135d <+93>:  leaq   -0x20(%rbp), %rsi
    0x100001361 <+97>:  movl   $0x21, %r8d
    0x100001367 <+103>: movq   %rdx, -0x38(%rbp)
    0x10000136b <+107>: movq   %r8, %rdx
    0x10000136e <+110>: movq   %rax, -0x40(%rbp)
    0x100001372 <+114>: callq  0x10000547a               ; symbol stub for: swift_beginAccess
    0x100001377 <+119>: movq   -0x40(%rbp), %rdi
    0x10000137b <+123>: movq   -0x38(%rbp), %rsi
    0x10000137f <+127>: leaq   0x5e72(%rip), %r13        ; TestSwift.str1 : Swift.String
    0x100001386 <+134>: callq  0x1000053d8               ; symbol stub for: Swift.String.append(Swift.String) -> ()
    0x10000138b <+139>: leaq   -0x20(%rbp), %rdi
    0x10000138f <+143>: callq  0x100005498               ; symbol stub for: swift_endAccess
    0x100001394 <+148>: movq   -0x38(%rbp), %rdi
    0x100001398 <+152>: callq  0x100005480               ; symbol stub for: swift_bridgeObjectRelease
    0x10000139d <+157>: xorl   %eax, %eax
    0x10000139f <+159>: addq   $0x38, %rsp
    0x1000013a3 <+163>: popq   %r13
    0x1000013a5 <+165>: popq   %rbp
    0x1000013a6 <+166>: retq   
    1. 重點(diǎn)觀察這一句0x10000137f <+127>: leaq 0x5e72(%rip), %r13 ; TestEnumMemory.str1 : Swift.String捕透,str1變量的地址時(shí)在r13寄存器中的聪姿,我們打印r13寄存器中的值,就可以得出str1變量的地址乙嘀,讀取str1變量的后 8個(gè)字節(jié)末购,我們發(fā)現(xiàn)從第33個(gè)字節(jié)開始,就是我們存儲(chǔ)的字符串了虎谢,有經(jīng)驗(yàn)的話盟榴,一眼就可以看出,str1變量的后8個(gè)字節(jié)婴噩,存放的是堆空間的地址擎场。
str1變量的地址從0x00000001000071f8開始的
(lldb) register read r13
r13 = 0x00000001000071f8  TestEnumMemory`TestEnumMemory.str1 : Swift.String

從0x00000001000071f8開始,讀取16個(gè)字節(jié)
(lldb) x/2xg  0x00000001000071f8
0x1000071f8: 0xf000000000000011 0x000000010070ac40

讀取 str1變量的后8個(gè)字節(jié)
(lldb) x/10xg 0x000000010070ac40
0x10070ac40: 0x00007fff9cc0fca8 0x0000000000000002
0x10070ac50: 0x0000000000000018 0xf000000000000011
0x10070ac60: 0x3736353433323130 0x4645444342413938
0x10070ac70: 0x00007fff93e30047 0x0000000000000000
0x10070ac80: 0x0000000000000000 0x0000000000000000
    1. 這里總結(jié)一下字符串的內(nèi)存
  • 如果一開始初始化時(shí)几莽,字符串長(zhǎng)度小于16時(shí)迅办,會(huì)直接把常量區(qū)字符串的內(nèi)容 ,拷貝到str1變量的內(nèi)存中章蚣,例如:var str1 = "0123456789"站欺,字符串的內(nèi)容就以ASCII的形式存儲(chǔ)在str1變量的內(nèi)存中

  • 如果一開始初始化時(shí),字符串長(zhǎng)度大于等于16時(shí)纤垂,字符串內(nèi)容會(huì)存放在常量區(qū)(__TEXT.cstring)镊绪,變量的前8個(gè)字節(jié)存放標(biāo)識(shí)符和字符串長(zhǎng)度,會(huì)把字符串的常量區(qū)的真實(shí)地址加上某個(gè)立即數(shù)洒忧,存放在變量的后8個(gè)字節(jié)中,例如:var str1 = "0123456789ABCDEF"够颠,str1變量的前8個(gè)字節(jié)存放標(biāo)識(shí)符和字符串長(zhǎng)度熙侍,后8個(gè)字節(jié)就存放著字符串的常量區(qū)地址+某個(gè)立即數(shù)

  • 如果字符串拼接之后如果仍然小于16時(shí),字符串的內(nèi)容還是存放在str1變量的內(nèi)存中履磨,例如:var str1 = "012345"; str1.append("ABCDE")蛉抓,拼接后字符串的內(nèi)容仍然在str1變量的內(nèi)存中

  • 如果字符串拼接之后長(zhǎng)度大于等于16,會(huì)開辟堆空間剃诅,變量的后8個(gè)字節(jié)存放著這個(gè)堆空間的地址信息巷送,堆空間的前32個(gè)字節(jié)存放描述信息,后面才是真正的字符串內(nèi)容矛辕,例如:var str1 = "012345678"; str1.append("ABCDEFGHEFSJ")笑跛,拼接之后付魔,就會(huì)開辟堆空間,str1變量的 后8個(gè)字節(jié)就是這個(gè)堆空間的地址飞蹂,堆空間里的前32個(gè)字節(jié)存放描述信息几苍,往后就是字符串的內(nèi)容

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市陈哑,隨后出現(xiàn)的幾起案子妻坝,更是在濱河造成了極大的恐慌,老刑警劉巖惊窖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刽宪,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡界酒,警方通過查閱死者的電腦和手機(jī)圣拄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盾计,“玉大人售担,你說我怎么就攤上這事∈鸹裕” “怎么了族铆?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)哭尝。 經(jīng)常有香客問我哥攘,道長(zhǎng),這世上最難降的妖魔是什么材鹦? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任逝淹,我火速辦了婚禮,結(jié)果婚禮上桶唐,老公的妹妹穿的比我還像新娘栅葡。我一直安慰自己,他們只是感情好尤泽,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布欣簇。 她就那樣靜靜地躺著,像睡著了一般坯约。 火紅的嫁衣襯著肌膚如雪熊咽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天闹丐,我揣著相機(jī)與錄音横殴,去河邊找鬼。 笑死卿拴,一個(gè)胖子當(dāng)著我的面吹牛衫仑,可吹牛的內(nèi)容都是我干的梨与。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼惑畴,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蛋欣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起如贷,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤陷虎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后杠袱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尚猿,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年楣富,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凿掂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纹蝴,死狀恐怖庄萎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情塘安,我是刑警寧澤糠涛,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站兼犯,受9級(jí)特大地震影響忍捡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜切黔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一砸脊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纬霞,春花似錦凌埂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绢陌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間熔恢,已是汗流浹背脐湾。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叙淌,地道東北人秤掌。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓愁铺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親闻鉴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子茵乱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349