iOS 內(nèi)存管理

# 前言

反復(fù)地復(fù)習(xí)iOS基礎(chǔ)知識(shí)和原理棕硫,打磨知識(shí)體系是非常重要的,本篇就是重新溫習(xí)iOS的內(nèi)存管理徘溢。

內(nèi)存管理是管理對(duì)象生命周期景东,在對(duì)象不需要時(shí)進(jìn)行內(nèi)存釋放的編程規(guī)范砂轻。

# 目錄

  • 前言

  • 目錄

  • MRC時(shí)代

    • 概要
    • Memory Management Policy 內(nèi)存管理策略
    • Practical Memory Management 實(shí)際內(nèi)存管理
    • 內(nèi)存管理實(shí)踐
      • 使用訪問(wèn)器方法使內(nèi)存管理更輕松
      • 使用訪問(wèn)器方法設(shè)置屬性
      • 不要在初始化和dealloc中使用訪問(wèn)器方法
      • 使用弱引用來(lái)避免循環(huán)引用
      • 避免正在使用的對(duì)象被釋放
      • Collections類(lèi)擁有它們所包含的對(duì)象所有權(quán)
      • 通過(guò)引用計(jì)數(shù)實(shí)現(xiàn)所有所有權(quán)策略
  • ARC時(shí)代

    • 概要
    • ARC 強(qiáng)制新規(guī)則
    • 內(nèi)存泄漏
    • block使用中出現(xiàn)循環(huán)引用
    • NSTimer循環(huán)引用
  • 參考資料

# MRC時(shí)代

概要

Objective-C內(nèi)存管理使用使用引用計(jì)數(shù)(Reference Counting)來(lái)管理內(nèi)存。

在OS X 10.8以后也不再使用垃圾回收機(jī)制斤吐,iOS則從來(lái)都沒(méi)有支持垃圾回收機(jī)制搔涝。

當(dāng)create或者copy對(duì)象時(shí)厨喂,會(huì)計(jì)數(shù)為1,其他對(duì)象需要retain時(shí)庄呈,會(huì)增加引用計(jì)數(shù)蜕煌。持有對(duì)象的所有者也可以放棄所有權(quán),放棄所有權(quán)時(shí)減少計(jì)數(shù)诬留,當(dāng)計(jì)數(shù)為0時(shí)就會(huì)釋放對(duì)象斜纪。
如圖:

memory_management 圖片來(lái)自官方文檔

Memory Management Policy 內(nèi)存管理策略

  • 通過(guò)分配內(nèi)存或copy來(lái)創(chuàng)建任何對(duì)象
  • 使用方法 alloc, allocWithZone:, copy, copyWithZone:, mutableCopy , mutableCopyWithZone:創(chuàng)建對(duì)象
  • 通過(guò)retain來(lái)獲取不是自己創(chuàng)建對(duì)象的所有權(quán)。以下兩種情況使用retain:
  1. accessor method或者init method方法獲取所需要的對(duì)象所有權(quán)為屬性property 文兑。
  2. 需要操作對(duì)象時(shí)盒刚,避免對(duì)象被釋放而導(dǎo)致錯(cuò)誤,需要retain持有對(duì)象绿贞。
  • 發(fā)送release, autorelease消息來(lái)釋放不需要的對(duì)象因块。
  • 不要不是你創(chuàng)建的對(duì)象和沒(méi)有所有權(quán)的對(duì)象發(fā)送release消息。

Practical Memory Management 實(shí)際內(nèi)存管理

  • Autorelease pools
  • 向?qū)ο蟀l(fā)送autorelease消息籍铁,會(huì)將對(duì)象標(biāo)記為延遲釋放涡上,當(dāng)對(duì)象超出當(dāng)前作用域時(shí),釋放對(duì)象拒名。
  • AppKit frameworksUIKit frameworks在事件循環(huán)的每個(gè)周期開(kāi)始時(shí)吩愧,在主線程上創(chuàng)建一個(gè)自動(dòng)釋放池,并在此次時(shí)間循環(huán)結(jié)束時(shí)靡狞,釋放它耻警,從而釋放在處理時(shí)生成的所有自動(dòng)釋放的對(duì)象。因此甸怕,通常不需要自己創(chuàng)建autoreleasePool,當(dāng)然腮恩,以下情況你需要自己創(chuàng)建和銷(xiāo)毀autoreleasePool
  1. 如果你編寫(xiě)的代碼不是基于UI framework的程序梢杭,如command-line tool命令行工具。
  2. 如果你需要寫(xiě)一個(gè)循環(huán)秸滴,創(chuàng)建許多臨時(shí)對(duì)象武契,如讀入大量的銅像同時(shí)改變圖片尺寸,圖像讀入到NSData對(duì)象荡含,并從中生成UIImage對(duì)象咒唆,改變?cè)搶?duì)象尺寸生成新的UIImage對(duì)象。
  3. 如果你創(chuàng)建一個(gè)長(zhǎng)期存在線程并且可能產(chǎn)生大量的autorelease對(duì)象释液。

autoreleasePool推薦使用以下方法:

@autoreleasepool {
 //do something
}
  • dealloc
    當(dāng)NSObject對(duì)象的引用計(jì)數(shù)為0時(shí)全释,銷(xiāo)毀該對(duì)象前會(huì)調(diào)用dealloc方法,用來(lái)釋放該對(duì)象擁有的所有資源误债,包裹實(shí)例變量指向的對(duì)象浸船。
    例子:
 // MRC
 - (void)dealloc{
    [_firstName release];
    [_lastName release];
    [super dealloc];
 }

Important: Never invoke another object’s dealloc method directly.You must invoke the superclass’s implementation at the end of your implementation.You should not tie management of system resources to object lifetimes; see Don’t Use dealloc to Manage Scarce Resources.When an application terminates, objects may not be sent a dealloc message. Because the process’s memory is automatically cleared on exit, it is more efficient simply to allow the operating system to clean up resources than to invoke all the memory management methods.
不要直接調(diào)用另一個(gè)對(duì)象的dealloc方法妄迁。你必須在類(lèi)使用結(jié)束時(shí)調(diào)用父類(lèi)的實(shí)現(xiàn)。你不應(yīng)該把系統(tǒng)資源與對(duì)象的生命周期綁定李命。
因?yàn)檫M(jìn)程的內(nèi)存退出時(shí)登淘,對(duì)象可能無(wú)法發(fā)送dealloc消息,該方法的內(nèi)存被自動(dòng)退出清零,所以讓操作系統(tǒng)清理資源比調(diào)用所有的內(nèi)存管理方法更有效。

內(nèi)存管理實(shí)踐

使用訪問(wèn)器方法使內(nèi)存管理更輕松

如果類(lèi)有一個(gè)屬性是一個(gè)對(duì)象封字,你必須確保使用該對(duì)象時(shí)黔州,它不會(huì)被釋放。因此在設(shè)置時(shí)阔籽,必須聲明對(duì)象的所有權(quán)流妻。還必須保證持有這些對(duì)象所有權(quán)的放棄。

  • 使用setget方法來(lái)實(shí)現(xiàn)仿耽,更方便管理內(nèi)存(主要是省寫(xiě)很多retainrelease)合冀。
    例子如下:
@interface Counter : NSObject
@property (nonatomic, retain) NSNumber *count;
@end;

Counter類(lèi)有一個(gè)屬性是NSNumber對(duì)象,屬性聲明了setget兩個(gè)訪問(wèn)器方法项贺,在get中就是返回synthesized實(shí)例變量君躺,所以沒(méi)必要retain或者release

- (NSNumber *)count {
 return _count;
}

set方法:

- (void)setCount:(NSNumber *)newCount {
    [newCount retain]; // 先`retain`確保新數(shù)據(jù)不被釋放
    [_count release];  // 釋放舊對(duì)象所有權(quán)
    // Make the new assignment.
    _count = newCount;  // 將新值賦給_count
}

retain確保新數(shù)據(jù)不被釋放,釋放舊的對(duì)象所有權(quán)(Objective-C允許向nil發(fā)送消息)开缎。你必須在[newCount retain]之后再[_count release]確保外部不會(huì)被dealloc棕叫。

使用訪問(wèn)器方法設(shè)置屬性

// 方法一
- (void)reset {
    NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
    [self setCount:zero];
    [zero release];
}
// 方法二
- (void)reset {
    NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
    [_count release];
    _count = zero;
}

方法二沒(méi)有對(duì)count屬性賦新值時(shí)沒(méi)有使用set訪問(wèn)方法,也不會(huì)觸發(fā)KVO奕删,可能在特殊情況導(dǎo)致錯(cuò)誤(比如忘記了 retain或者release俺泣,或者如果實(shí)例變量的內(nèi)存管理發(fā)生了變化)。除了第一種方法完残,或者直接使用self.count = zero;伏钠。

不要在初始化和dealloc中使用訪問(wèn)器方法

不應(yīng)該使用setget方法在initdealloc。應(yīng)該使用_直接訪問(wèn)成員變量進(jìn)行初始化和dealloc谨设。如下:

- init {
    self = [super init];
    if (self) {
        _count = [[NSNumber alloc] initWithInteger:0];
    }
    return self;
}
// 由于Counter類(lèi)具有對(duì)象實(shí)例變量熟掂,因此還必須實(shí)現(xiàn)dealloc方法。
// 它應(yīng)該通過(guò)向任何實(shí)例變量發(fā)送一個(gè)釋放消息來(lái)放棄它的所有權(quán)扎拣,最終它應(yīng)該調(diào)用super的實(shí)現(xiàn)
- (void)dealloc {
    [_count release];
    [super dealloc];
}

使用弱引用來(lái)避免循環(huán)引用

  • retain對(duì)象赴肚,實(shí)際是對(duì)對(duì)象的強(qiáng)引用(strong reference),一個(gè)對(duì)象在所有強(qiáng)引用都沒(méi)有被釋放之前,不能釋放對(duì)象二蓝。因此誉券,如果有兩個(gè)對(duì)象互相持有對(duì)方或者間接互相引用,會(huì)導(dǎo)致循環(huán)引用刊愚。這時(shí)候就需要弱引用對(duì)方來(lái)打破這個(gè)循環(huán)踊跟。

如父親強(qiáng)引用兒子,兒子強(qiáng)引用孫子百拓,那么倒過(guò)來(lái)孫子只能弱引用兒子琴锭,兒子也只能弱引用父親晰甚。Cocoa建立了一個(gè)約定,副對(duì)象應(yīng)該強(qiáng)引用子對(duì)象决帖,并且子對(duì)象應(yīng)該只對(duì)父對(duì)象弱引用厕九。
Cocoa中常見(jiàn)的例子包括代理方法delegatedata source,observer,target等等

必須小心將消息發(fā)送到持有只是一個(gè)弱引用的對(duì)象地回。當(dāng)發(fā)送消息給一個(gè)被dealloc的弱引用對(duì)象時(shí)扁远,你的應(yīng)用程序會(huì)崩潰(這是在MRC時(shí)期的代理delegate會(huì)出現(xiàn),因?yàn)楫?dāng)時(shí)對(duì)代理弱引用的修飾符是assign,assign弱引用并不會(huì)在對(duì)象dealloc時(shí)刻像,把對(duì)象置為nil畅买。而ARC時(shí)代使用weak則會(huì)在對(duì)象dealloc時(shí)置為nil)。

避免正在使用的對(duì)象被釋放

  • Cocoa的所有權(quán)策略規(guī)定接收的對(duì)象通常在整個(gè)調(diào)用方法的范圍內(nèi)保證有效细睡。還應(yīng)該是在當(dāng)前方法范圍內(nèi)谷羞,而不必?fù)?dān)心它被釋放。對(duì)象的getter方法返回一個(gè)緩存的實(shí)例變量或者一個(gè)計(jì)算的值溜徙,這不重要湃缎,重要的是,對(duì)象在需要的使用時(shí)還是有效的蠢壹。
  • 有兩類(lèi)例外情況:
  • 當(dāng)一個(gè)對(duì)象從基本的集合類(lèi)刪除時(shí)
heisenObject = [array objectAtIndex:n];
[array removeObjectAtIndex:n];
// heisenObject 現(xiàn)在可能無(wú)效
  • n從集合array刪除時(shí)也會(huì)向n發(fā)送release(而不是autorelease)消息嗓违。如果array集合時(shí)被刪除n對(duì)象的唯一擁有者,被移除的對(duì)象n是立即被釋放的图贸。heisenObject并沒(méi)有對(duì)n進(jìn)行retain蹂季,所以當(dāng)narray刪除時(shí)同時(shí)被釋放。

正確的做法

heisenObject = [[array objectAtIndex:n] retain];
[array removeObjectAtIndex:n];
// Use heisenObject...
[heisenObject release];
  • 當(dāng)一個(gè)父對(duì)象被釋放時(shí)
id parent = <#create a parent object#>;
// ...
heisenObject = [parent child] ;
[parent release]; // Or, for example: self.parent = nil;
// heisenObject 現(xiàn)在可能無(wú)效
  • 在某些情況下疏日,從另一個(gè)對(duì)象獲取的對(duì)象偿洁,然后直接或者間接的釋放負(fù)對(duì)象。如果釋放父對(duì)象導(dǎo)致它被釋放沟优,并且父對(duì)象是子對(duì)象唯一所有者父能,那么子對(duì)象heisenObject將被同一時(shí)間釋放。所以正確的做法還是子對(duì)象heisenObject獲取的時(shí)候先retain一次净神。

Collections類(lèi)擁有它們所包含的對(duì)象所有權(quán)

  • 添加一個(gè)對(duì)象到一個(gè)collection中,如(數(shù)組溉委、字典鹃唯、集合)時(shí),collection會(huì)得到該對(duì)象所有權(quán)瓣喊。當(dāng)對(duì)象從collection刪除或者collection自己被釋放時(shí)坡慌,collection將釋放它擁有的所有權(quán)。
NSMutableArray *array = <#Get a mutable array#>;
NSUInteger i;
// ...
for (i = 0; i < 10; i++) {
    NSNumber *allocedNumber = [[NSNumber alloc] initWithInteger:i];
    [array addObject:allocedNumber];
    [allocedNumber release];
}

通過(guò)引用計(jì)數(shù)實(shí)現(xiàn)所有所有權(quán)策略

  • 所有圈策略是通過(guò)引用計(jì)數(shù)實(shí)現(xiàn)的藻三,通常retain方法后被稱(chēng)為retain count洪橘。每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)跪者。

  • 當(dāng)你創(chuàng)建一個(gè)對(duì)象,它的引用計(jì)數(shù)為1

  • 當(dāng)你給對(duì)象發(fā)送retain消息熄求,引用計(jì)數(shù)+1

  • 當(dāng)你給對(duì)象發(fā)送release消息渣玲,引用計(jì)數(shù)-1

  • 當(dāng)你給對(duì)象發(fā)送一個(gè)autorelease消息,它的引用計(jì)數(shù)器將在當(dāng)前的自動(dòng)釋放池結(jié)束后-1

  • 當(dāng)對(duì)象的引用計(jì)數(shù)為0時(shí)將被釋放

# ARC時(shí)代

概要

iOS5后出現(xiàn)了ARC弟晚。那么ARC是什么呢忘衍?
自動(dòng)引用計(jì)數(shù)ARC是一種編譯器的功能,為Objective-C對(duì)象提供了自動(dòng)化的內(nèi)存管理卿城。
ARC不需要開(kāi)發(fā)者考慮保留或者釋放的操作枚钓,就是不用自己手動(dòng)retainreleaseautorelease(??開(kāi)心)瑟押,讓開(kāi)發(fā)者可以專(zhuān)注寫(xiě)有趣的代碼搀捷。
當(dāng)然ARC依然是基于引用計(jì)數(shù)管理內(nèi)存。

ARC 強(qiáng)制新規(guī)則

ARC相對(duì)于MRC強(qiáng)制加了一些新的規(guī)則多望。

  • 你不能主動(dòng)調(diào)用dealloc嫩舟、或者調(diào)用retain,release, retainCount,autorelease就是這些都不用你寫(xiě)了。也不能@selector(retain), @selector(release)這樣子調(diào)用便斥。
  • 你可以實(shí)現(xiàn)一個(gè)dealloc方法至壤,如果你需要管理資源而不是釋放實(shí)例變量(比如解除監(jiān)聽(tīng)、釋放引用枢纠、socket close等等)像街。在重寫(xiě)dealloc后需要[super dealloc](在手動(dòng)管理引用計(jì)數(shù)時(shí)才需要)。
  • 仍然可以使用CFRetain晋渺,CFRelease等其它對(duì)象镰绎。
  • 你不能使用NSAllocateObject或者NSDeallocateObject
  • 你不能使用C結(jié)構(gòu)體木西,可以創(chuàng)建一個(gè)Objective-C類(lèi)去管理數(shù)據(jù)而不是一個(gè)結(jié)構(gòu)體畴栖。
  • idvoid沒(méi)有轉(zhuǎn)換關(guān)系,你必須使用cast特殊方式,以便在作為函數(shù)參數(shù)傳遞的Objective-C對(duì)象和Core Foundation類(lèi)型之間進(jìn)行轉(zhuǎn)換八千。
  • 你不能使用NSAutoreleasePool吗讶,使用@autoreleasepool
  • 沒(méi)必要使用NSZone

ARC 使用新修飾符

  • __strong 強(qiáng)引用,用來(lái)保證對(duì)象不會(huì)被釋放恋捆。
  • __weak弱引用 釋放時(shí)會(huì)置為nil
  • __unsafe_unretained弱引用 可能不安全照皆,因?yàn)獒尫艜r(shí)不置為nil
  • __autoreleasing對(duì)象被注冊(cè)到autorelease pool中方法在返回時(shí)自動(dòng)釋放沸停。

內(nèi)存泄漏

ARC還是基于引用計(jì)數(shù)的管理機(jī)制所以依然會(huì)出現(xiàn)循環(huán)引用膜毁。

block使用中出現(xiàn)循環(huán)引用

  • 常見(jiàn)的有情況在block使用中出現(xiàn)循環(huán)引用
// 情況一
self.myBlock = ^{
self.objc = ...;
};
// 情況二
Dog *dog = [[Dog alloc] init];
dog.myBlock = ^{
  // do something
};
self.dog = dog;
  • 解決方法
__weak typeof (self) weakSelf = self;
self.myBlock = ^{
weakSelf.objc = ...;
};
  • 那么如果block內(nèi)使用了self這個(gè)時(shí)候如果某一個(gè)時(shí)刻self被釋放就會(huì)導(dǎo)致出現(xiàn)問(wèn)題。
  • 解決方法
__weak typeof (self) weakSelf = self;
self.myBlock = ^{
__strong typeof(self) strongSelf = weakSelf;
strongSelf.objc1 = ...;
strongSelf.objc2 = ...;
strongSelf.objc3 = ...;
};
  • 使用__weak打破循環(huán)引用。__strong用來(lái)避免在使用self過(guò)程中self被釋放瘟滨,__strongblock后會(huì)調(diào)用objc_release(obj)釋放對(duì)象候醒。
id __strong obj = [[NSObject alloc] init];

// clang 編譯后
id obj = objc_msgSend(NSObject, @selector(alloc));
objc_msgSend(obj, @selector(init));
objc_release(obj);

兩次調(diào)用objc_msgSend并在變量作用域結(jié)束時(shí)調(diào)用objc_release釋放對(duì)象,不會(huì)出現(xiàn)循環(huán)引用問(wèn)題杂瘸。

NSTimer循環(huán)引用

為什么NSTimer會(huì)導(dǎo)致循環(huán)引用呢倒淫?

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti 
           target:(id)aTarget 
           selector:(SEL)aSelector 
           userInfo:(nullable id)userInfo 
           repeats:(BOOL)yesOrNo;
           
           
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti 
                  target:(id)aTarget 
                  selector:(SEL)aSelector 
                  userInfo:(nullable id)userInfo 
                  repeats:(BOOL)yesOrNo;
  • 主要是因?yàn)?code>NSRunloop運(yùn)行循環(huán)保持了對(duì)NSTimer的強(qiáng)引用,并且NSTimertarger也使用了強(qiáng)引用胧沫。

  • 來(lái)自文檔NSTimer

Note in particular that run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.
target
The object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to this object until it (the timer) is invalidated.

舉個(gè)??:


@interface ViewController ()<viewControllerDelegate>

@property (strong, nonatomic) NSTimer *timer;

@end

 - (void)viewDidLoad
 {
     [super viewDidLoad];
     self.timer = [NSTimer scheduledTimerWithTimeInterval:1
                                               target:self 
                                             selector:@selector(onTimeOut:) 
                                             userInfo:nil 
                                              repeats:NO];
 }
  • 這里控制器強(qiáng)引用了timer昌简,而timer也強(qiáng)引用了控制器,這個(gè)時(shí)候就是循環(huán)引用了,引用關(guān)系如下圖:
retain cycle
  • 那么如果控制器對(duì)timer使用了weak呢绒怨?
    使用weak是打破了循環(huán)引用,但是run loop還是強(qiáng)引用著timer,timer又強(qiáng)引用著控制器纯赎,所以還是會(huì)導(dǎo)致內(nèi)存泄漏。引用關(guān)系如下圖:
leak

如果我們把timer加入主線程的runloop,主線程中的runloop生命周期只有主線程結(jié)束才會(huì)銷(xiāo)毀南蹂,所以我們不主動(dòng)調(diào)用[timer invalidate],runloop會(huì)一直持有timer犬金,timer又持有控制器,那么就一直不會(huì)釋放控制器六剥。

  • 解決方法:手動(dòng)調(diào)用[timer invalidate]來(lái)解除持有關(guān)系晚顷,釋放內(nèi)存×婆保可能會(huì)想到在dealloc方法中來(lái)手動(dòng)調(diào)用该默,但是因?yàn)?code>timer持有控制器,所以控制器的dealloc方法永遠(yuǎn)不會(huì)調(diào)用策彤,因?yàn)?code>dealloc是在控制器要被釋放前調(diào)用的栓袖。在Timer Programming Topics中有特別說(shuō)明。所以一般我們可以在下面這些方法中手動(dòng)調(diào)用[timer invalidate]然后置為nil
- (void)viewWillDisappear:(BOOL)animated; // Called when the view is dismissed, covered or otherwise hidden. Default does nothing
- (void)viewDidDisappear:(BOOL)animated;  // Called after the view was dismissed, covered or otherwise hidden. Default does nothing

A timer maintains a strong reference to its target. This means that as long as a timer remains valid, its target will not be deallocated. As a corollary, this means that it does not make sense for a timer’s target to try to invalidate the timer in its dealloc method—the dealloc method will not be invoked as long as the timer is valid.

# 參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末店诗,一起剝皮案震驚了整個(gè)濱河市裹刮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庞瘸,老刑警劉巖捧弃,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異擦囊,居然都是意外死亡违霞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)瞬场,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)葛家,“玉大人,你說(shuō)我怎么就攤上這事泌类。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵刃榨,是天一觀的道長(zhǎng)弹砚。 經(jīng)常有香客問(wèn)我,道長(zhǎng)枢希,這世上最難降的妖魔是什么桌吃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮苞轿,結(jié)果婚禮上茅诱,老公的妹妹穿的比我還像新娘。我一直安慰自己搬卒,他們只是感情好瑟俭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著契邀,像睡著了一般摆寄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坯门,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天微饥,我揣著相機(jī)與錄音,去河邊找鬼古戴。 笑死欠橘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的现恼。 我是一名探鬼主播肃续,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼述暂!你這毒婦竟也來(lái)了痹升?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤畦韭,失蹤者是張志新(化名)和其女友劉穎疼蛾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體艺配,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡察郁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了转唉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片皮钠。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赠法,靈堂內(nèi)的尸體忽然破棺而出麦轰,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布款侵,位于F島的核電站末荐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏新锈。R本人自食惡果不足惜甲脏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妹笆。 院中可真熱鬧块请,春花似錦、人聲如沸拳缠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)脊凰。三九已至抖棘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狸涌,已是汗流浹背切省。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帕胆,地道東北人朝捆。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像懒豹,于是被迫代替她去往敵國(guó)和親芙盘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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