iOS異常處理

開(kāi)發(fā)iOS應(yīng)用病曾,解決Crash問(wèn)題始終是一個(gè)難題锨侯。Crash分為兩種斤斧,
一種是由EXC_BAD_ACCESS引起的勺美,原因是訪(fǎng)問(wèn)了不屬于本進(jìn)程的內(nèi)存地址递胧,有可能是訪(fǎng)問(wèn)已被釋放的內(nèi)存;
另一種是未被捕獲的目標(biāo)C異常(NSException)記錄,導(dǎo)致程序向自身發(fā)送了SIGABRT信號(hào)而崩潰赡茸。
其實(shí)對(duì)于未捕獲的目標(biāo)C異常缎脾,我們是有辦法將它記錄下來(lái)的,如果日志記錄得當(dāng)占卧,能夠解決絕大部分崩潰的問(wèn)題遗菠。這里對(duì)于UI線(xiàn)程與后臺(tái)線(xiàn)程分別說(shuō)明

一、系統(tǒng)崩潰
對(duì)于系統(tǒng)崩潰而引起的程序異常退出华蜒,可以通過(guò)NSSetUncaughtExceptionHandler機(jī)制捕獲辙纬,代碼:實(shí)現(xiàn)一個(gè)用于處理異常的方法

void HandleException(NSException *exception)  {

    // 異常的堆棧信息
    NSArray *stackArray = [exception callStackSymbols];

    // 出現(xiàn)異常的原因
    NSString *reason = [exception reason];

    // 異常名稱(chēng)
    NSString *name = [exception name];

    NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];

    NSLog(@"%@", exceptionInfo);
    NSString *logPath=[NSString stringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()];
[exceptionInfo writeToFile:logPath  atomically:YES encoding:NSUTF8StringEncoding error:nil];
}

然后在啟動(dòng)appdidFinishLaunchingWithOptions的時(shí)候設(shè)置

NSSetUncaughtExceptionHandler (&UncaughtExceptionHandlers);//系統(tǒng)異常捕獲

當(dāng)捕獲到異常時(shí),就會(huì)調(diào)用UncaughtExceptionHandlers來(lái)出來(lái)異常

二叭喜、處理signal
使用Objective-C的異常處理是不能得到signal的贺拣,如果要處理它,我們還要利用unix標(biāo)準(zhǔn)的signal機(jī)制,注冊(cè)SIGABRT, SIGBUS, SIGSEGV等信號(hào)發(fā)生時(shí)的處理函數(shù)譬涡。該函數(shù)中我們可以輸出棧信息闪幽,版本信息等其他一切我們所想要的。NSSetUncaughtExceptionHandler 用來(lái)做異常處理涡匀,但功能非常有限.而引起崩潰的大多數(shù)原因如:內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤沟使,重復(fù)釋放等錯(cuò)誤就無(wú)能為力了,因?yàn)檫@種錯(cuò)誤它拋出的是Signal渊跋,所以必須要專(zhuān)門(mén)做Signal處理,代碼如下:
首先定義一個(gè)UncaughtExceptionHandler類(lèi)着倾,用來(lái)捕獲處理所有的崩潰信息

@interface UncaughtExceptionHandler : NSObject  {
    BOOL dismissed;
}
+ (void)InstallUncaughtExceptionHandler;
@end

#import <UIKit/UIKit.h>
#import "UncaughtExceptionHandler.h"
#include <libkern/OSAtomic.h>
#include <execinfo.h>

NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";
NSString * const UncaughtExceptionHandlerFileKey = @"UncaughtExceptionHandlerFileKey";

volatile int32_t UncaughtExceptionCount = 0;
const int32_t UncaughtExceptionMaximum = 10;
const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;

void MySignalHandler(int signal);


@implementation UncaughtExceptionHandler

+ (void)InstallUncaughtExceptionHandler {
    NSSetUncaughtExceptionHandler (&UncaughtExceptionHandlers);////系統(tǒng)異常捕獲(越界)
    //信號(hào)量截?cái)?    signal(SIGABRT, MySignalHandler);
    signal(SIGILL, MySignalHandler);
    signal(SIGSEGV, MySignalHandler);
    signal(SIGFPE, MySignalHandler);
    signal(SIGBUS, MySignalHandler);
    signal(SIGPIPE, MySignalHandler);
}

//獲取函數(shù)堆棧信息
+ (NSArray *)backtrace {

    void* callstack[128];
    int frames = backtrace(callstack, 128);//用于獲取當(dāng)前線(xiàn)程的函數(shù)調(diào)用堆棧拾酝,返回實(shí)際獲取的指針個(gè)數(shù)
    char **strs = backtrace_symbols(callstack, frames);//從backtrace函數(shù)獲取的信息轉(zhuǎn)化為一個(gè)字符串?dāng)?shù)組
    int i;
    NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
    for (i = UncaughtExceptionHandlerSkipAddressCount;
     i < UncaughtExceptionHandlerSkipAddressCount+UncaughtExceptionHandlerReportAddressCount;
     i++)  {
        [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
    }
    free(strs);
    return backtrace;
}

- (void)saveCreash:(NSException *)exception file:(NSString *)file {
    NSArray *stackArray = [exception callStackSymbols];// 異常的堆棧信息
    NSString *reason = [exception reason];// 出現(xiàn)異常的原因
    NSString *name = [exception name];// 異常名稱(chēng)

    //或者直接用代碼,輸入這個(gè)崩潰信息卡者,以便在console中進(jìn)一步分析錯(cuò)誤原因
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);


    NSString * _libPath  = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:file];

//    NSString *_libPath=[NSHomeDirectory() stringByAppendingPathComponent:file];

    if (![[NSFileManager defaultManager] fileExistsAtPath:_libPath]) {
        [[NSFileManager defaultManager] createDirectoryAtPath:_libPath withIntermediateDirectories:YES attributes:nil error:nil];
    }

    NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
    NSTimeInterval a=[dat timeIntervalSince1970];
    NSString *timeString = [NSString stringWithFormat:@"%f", a];

    NSString * savePath = [_libPath stringByAppendingFormat:@"/error%@.log",timeString];

    NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];

    BOOL sucess = [exceptionInfo writeToFile:savePath atomically:YES encoding:NSUTF8StringEncoding error:nil];

    NSLog(@"保存崩潰日志 sucess:%d,%@",sucess,savePath);
}

//異常處理方法
- (void)handleException:(NSException *)exception {
    NSDictionary *userInfo=[exception userInfo];
    [self saveCreash:exception file:[userInfo objectForKey:UncaughtExceptionHandlerFileKey]];    

    NSSetUncaughtExceptionHandler(NULL);
    signal(SIGABRT, SIG_DFL);
    signal(SIGILL, SIG_DFL);
    signal(SIGSEGV, SIG_DFL);
    signal(SIGFPE, SIG_DFL);
    signal(SIGBUS, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
    if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName]) 
        kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
    } else {
        [exception raise];
    }
}    

//獲取應(yīng)用信息
NSString* getAppInfo() {
    NSString *appInfo = [NSString stringWithFormat:@"App : %@ %@(%@)\nDevice : %@\nOS Version : %@ %@\n",
                     [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],
                     [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"],
                     [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"],
                     [UIDevice currentDevice].model,
                     [UIDevice currentDevice].systemName,
                     [UIDevice currentDevice].systemVersion];
//                         [UIDevice currentDevice].uniqueIdentifier];
    NSLog(@"Crash!!!! %@", appInfo);
    return appInfo;
}

//NSSetUncaughtExceptionHandler捕獲異常的調(diào)用方法
//利用 NSSetUncaughtExceptionHandler蒿囤,當(dāng)程序異常退出的時(shí)候,可以先進(jìn)行處理崇决,然后做一些自定義的動(dòng)作
void UncaughtExceptionHandlers (NSException *exception) {

    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
    if (exceptionCount > UncaughtExceptionMaximum)
    {
        return;
    }

    NSArray *callStack = [UncaughtExceptionHandler backtrace];
    NSMutableDictionary *userInfo =
    [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
    [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
    [userInfo setObject:@"OCCrash" forKey:UncaughtExceptionHandlerFileKey];


    [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:) 
                                                              withObject:[NSException exceptionWithName:[exception name]
                                                                  reason:[exception reason] userInfo:userInfo] 
                                                           waitUntilDone:YES]; 
}

//Signal處理方法
void MySignalHandler(int signal) {
    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);//自動(dòng)增加一個(gè)32位的值
    if (exceptionCount > UncaughtExceptionMaximum)
    {
        return;
    }

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];
    NSArray *callStack = [UncaughtExceptionHandler backtrace];
    [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
    [userInfo setObject:@"SigCrash" forKey:UncaughtExceptionHandlerFileKey];

    [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:) 
                                                              withObject:[NSException exceptionWithName:UncaughtExceptionHandlerSignalExceptionName 
                                                                  reason:[NSString stringWithFormat:NSLocalizedString(@"Signal %d was raised.\n" @"%@", nil), signal, getAppInfo()] userInfo:userInfo]
                                                           waitUntilDone:YES]; 
}
@end

最后材诽,在didFinishLaunchingWithOptions中調(diào)用該函數(shù)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[UncaughtExceptionHandler InstallUncaughtExceptionHandler];//捕獲內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤,處理Signal
return YES;
}
三、測(cè)試
當(dāng)運(yùn)行時(shí)遇到系統(tǒng)錯(cuò)誤或內(nèi)存錯(cuò)誤Signal恒傻,就會(huì)被截獲處理并把錯(cuò)誤日志保存下來(lái)(一般可等下次啟動(dòng)時(shí)判斷一下脸侥,把日志上傳),可自己測(cè)試一下:

/1.信號(hào)量
int list[2]={1,2};
int *p = list;
free(p);//導(dǎo)致SIGABRT的錯(cuò)誤盈厘,因?yàn)閮?nèi)存中根本就沒(méi)有這個(gè)空間睁枕,哪來(lái)的free,就在棧中的對(duì)象而已
p[1] = 5;

//2.ios崩潰
NSArray *array= @[@"tom",@"xxx",@"ooo"];
[array objectAtIndex:5];

PS: SignalHandler不要在debug環(huán)境下測(cè)試沸手。因?yàn)橄到y(tǒng)的debug會(huì)優(yōu)先去攔截外遇。我們要運(yùn)行一次后,關(guān)閉debug狀態(tài)契吉。應(yīng)該直接在模擬器上點(diǎn)擊我們build上去的app去運(yùn)行跳仿。而UncaughtExceptionHandler可以在調(diào)試狀態(tài)下捕捉。

附錄科普:

一些信號(hào)說(shuō)明

  1. SIGHUP 本信號(hào)在用戶(hù)終端連接(正尘杈В或非正常)結(jié)束時(shí)發(fā)出, 通常是在終端的控制進(jìn)程結(jié)束時(shí), 通知同一session內(nèi)的各個(gè)作業(yè), 這時(shí)它們與控制終端不再關(guān)聯(lián)菲语。 登錄Linux時(shí),系統(tǒng)會(huì)分配給登錄用戶(hù)一個(gè)終端(Session)租悄。在這個(gè)終端運(yùn)行的所有程序谨究,包括前臺(tái)進(jìn)程組和后臺(tái)進(jìn)程組,一般都屬于這個(gè) Session泣棋。當(dāng)用戶(hù)退出Linux登錄時(shí)胶哲,前臺(tái)進(jìn)程組和后臺(tái)有對(duì)終端輸出的進(jìn)程將會(huì)收到SIGHUP信號(hào)。這個(gè)信號(hào)的默認(rèn)操作為終止進(jìn)程潭辈,因此前臺(tái)進(jìn) 程組和后臺(tái)有終端輸出的進(jìn)程就會(huì)中止鸯屿。不過(guò)可以捕獲這個(gè)信號(hào)澈吨,比如wget能捕獲SIGHUP信號(hào),并忽略它寄摆,這樣就算退出了Linux登錄谅辣, wget也 能繼續(xù)下載。 此外婶恼,對(duì)于與終端脫離關(guān)系的守護(hù)進(jìn)程桑阶,這個(gè)信號(hào)用于通知它重新讀取配置文件。

  2. SIGINT 程序終止(interrupt)信號(hào), 在用戶(hù)鍵入INTR字符(通常是Ctrl-C)時(shí)發(fā)出勾邦,用于通知前臺(tái)進(jìn)程組終止進(jìn)程蚣录。

  3. SIGQUIT 和SIGINT類(lèi)似, 但由QUIT字符(通常是Ctrl-)來(lái)控制. 進(jìn)程在因收到SIGQUIT退出時(shí)會(huì)產(chǎn)生core文件, 在這個(gè)意義上類(lèi)似于一個(gè)程序錯(cuò)誤信號(hào)。

  4. SIGILL 執(zhí)行了非法指令. 通常是因?yàn)榭蓤?zhí)行文件本身出現(xiàn)錯(cuò)誤, 或者試圖執(zhí)行數(shù)據(jù)段. 堆棧溢出時(shí)也有可能產(chǎn)生這個(gè)信號(hào)眷篇。

  5. SIGTRAP 由斷點(diǎn)指令或其它trap指令產(chǎn)生. 由debugger使用萎河。

  6. SIGABRT 調(diào)用abort函數(shù)生成的信號(hào)。

  7. SIGBUS 非法地址, 包括內(nèi)存地址對(duì)齊(alignment)出錯(cuò)蕉饼。比如訪(fǎng)問(wèn)一個(gè)四個(gè)字長(zhǎng)的整數(shù), 但其地址不是4的倍數(shù)虐杯。它與SIGSEGV的區(qū)別在于后者是由于對(duì)合法存儲(chǔ)地址的非法訪(fǎng)問(wèn)觸發(fā)的(如訪(fǎng)問(wèn)不屬于自己存儲(chǔ)空間或只讀存儲(chǔ)空間)。

  8. SIGFPE 在發(fā)生致命的算術(shù)運(yùn)算錯(cuò)誤時(shí)發(fā)出. 不僅包括浮點(diǎn)運(yùn)算錯(cuò)誤, 還包括溢出及除數(shù)為0等其它所有的算術(shù)的錯(cuò)誤昧港。

  9. SIGKILL 用來(lái)立即結(jié)束程序的運(yùn)行. 本信號(hào)不能被阻塞擎椰、處理和忽略。如果管理員發(fā)現(xiàn)某個(gè)進(jìn)程終止不了慨飘,可嘗試發(fā)送這個(gè)信號(hào)确憨。

  10. SIGUSR1 留給用戶(hù)使用

  11. SIGSEGV 試圖訪(fǎng)問(wèn)未分配給自己的內(nèi)存, 或試圖往沒(méi)有寫(xiě)權(quán)限的內(nèi)存地址寫(xiě)數(shù)據(jù).

  12. SIGUSR2 留給用戶(hù)使用

  13. SIGPIPE 管道破裂。這個(gè)信號(hào)通常在進(jìn)程間通信產(chǎn)生瓤的,比如采用FIFO(管道)通信的兩個(gè)進(jìn)程休弃,讀管道沒(méi)打開(kāi)或者意外終止就往管道寫(xiě),寫(xiě)進(jìn)程會(huì)收到SIGPIPE信號(hào)圈膏。此外用Socket通信的兩個(gè)進(jìn)程塔猾,寫(xiě)進(jìn)程在寫(xiě)Socket的時(shí)候,讀進(jìn)程已經(jīng)終止稽坤。

  14. SIGALRM 時(shí)鐘定時(shí)信號(hào), 計(jì)算的是實(shí)際的時(shí)間或時(shí)鐘時(shí)間. alarm函數(shù)使用該信號(hào).

  15. SIGTERM 程序結(jié)束(terminate)信號(hào), 與SIGKILL不同的是該信號(hào)可以被阻塞和處理丈甸。通常用來(lái)要求程序自己正常退出,shell命令kill缺省產(chǎn)生這個(gè)信號(hào)尿褪。如果進(jìn)程終止不了睦擂,我們才會(huì)嘗試SIGKILL。

  16. SIGCHLD 子進(jìn)程結(jié)束時(shí), 父進(jìn)程會(huì)收到這個(gè)信號(hào)杖玲。 如果父進(jìn)程沒(méi)有處理這個(gè)信號(hào)顿仇,也沒(méi)有等待(wait)子進(jìn)程,子進(jìn)程雖然終止,但是還會(huì)在內(nèi)核進(jìn)程表中占有表項(xiàng)臼闻,這時(shí)的子進(jìn)程稱(chēng)為僵尸進(jìn)程鸿吆。這種情 況我們應(yīng)該避免(父進(jìn)程或者忽略SIGCHILD信號(hào),或者捕捉它述呐,或者wait它派生的子進(jìn)程惩淳,或者父進(jìn)程先終止乓搬,這時(shí)子進(jìn)程的終止自動(dòng)由init進(jìn)程 來(lái)接管)进肯。

  17. SIGCONT 讓一個(gè)停止(stopped)的進(jìn)程繼續(xù)執(zhí)行. 本信號(hào)不能被阻塞. 可以用一個(gè)handler來(lái)讓程序在由stopped狀態(tài)變?yōu)槔^續(xù)執(zhí)行時(shí)完成特定的工作. 例如, 重新顯示提示符

  18. SIGSTOP 停止(stopped)進(jìn)程的執(zhí)行. 注意它和terminate以及interrupt的區(qū)別:該進(jìn)程還未結(jié)束, 只是暫停執(zhí)行. 本信號(hào)不能被阻塞, 處理或忽略.

  19. SIGTSTP 停止進(jìn)程的運(yùn)行, 但該信號(hào)可以被處理和忽略. 用戶(hù)鍵入SUSP字符時(shí)(通常是Ctrl-Z)發(fā)出這個(gè)信號(hào)

  20. SIGTTIN 當(dāng)后臺(tái)作業(yè)要從用戶(hù)終端讀數(shù)據(jù)時(shí), 該作業(yè)中的所有進(jìn)程會(huì)收到SIGTTIN信號(hào). 缺省時(shí)這些進(jìn)程會(huì)停止執(zhí)行.

  21. SIGTTOU 類(lèi)似于SIGTTIN, 但在寫(xiě)終端(或修改終端模式)時(shí)收到.

  22. SIGURG 有”緊急”數(shù)據(jù)或out-of-band數(shù)據(jù)到達(dá)socket時(shí)產(chǎn)生.

  23. SIGXCPU 超過(guò)CPU時(shí)間資源限制. 這個(gè)限制可以由getrlimit/setrlimit來(lái)讀取/改變含蓉。

  24. SIGXFSZ 當(dāng)進(jìn)程企圖擴(kuò)大文件以至于超過(guò)文件大小資源限制斟赚。

  25. SIGVTALRM 虛擬時(shí)鐘信號(hào). 類(lèi)似于SIGALRM, 但是計(jì)算的是該進(jìn)程占用的CPU時(shí)間.

  26. SIGPROF 類(lèi)似于SIGALRM/SIGVTALRM, 但包括該進(jìn)程用的CPU時(shí)間以及系統(tǒng)調(diào)用的時(shí)間.

  27. SIGWINCH 窗口大小改變時(shí)發(fā)出.

  28. SIGIO 文件描述符準(zhǔn)備就緒, 可以開(kāi)始進(jìn)行輸入/輸出操作.

  29. SIGPWR Power failure

  30. SIGSYS 非法的系統(tǒng)調(diào)用。

關(guān)鍵點(diǎn)注意

在以上列出的信號(hào)中,程序不可捕獲刃鳄、阻塞或忽略的信號(hào)有:SIGKILL,SIGSTOP 不能恢復(fù)至默認(rèn)動(dòng)作的信號(hào)有:SIGILL,SIGTRAP 默認(rèn)會(huì)導(dǎo)致進(jìn)程流產(chǎn)的信號(hào)有:SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGIOT,SIGQUIT,SIGSEGV,SIGTRAP,SIGXCPU,SIGXFSZ 默認(rèn)會(huì)導(dǎo)致進(jìn)程退出的信號(hào)有: SIGALRM,SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,SIGSYS,SIGTERM,SIGUSR1,SIGUSR2,SIGVTALRM 默認(rèn)會(huì)導(dǎo)致進(jìn)程停止的信號(hào)有:SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU 默認(rèn)進(jìn)程忽略的信號(hào)有:SIGCHLD,SIGPWR,SIGURG,SIGWINCH 此外,SIGIO在SVR4是退出愉烙,在4.3BSD中是忽略;SIGCONT在進(jìn)程掛起時(shí)是繼續(xù)勺择,否則是忽略稿辙,不能被阻塞。

Crash Callstack分析 – 進(jìn)?一步分析

屬性 說(shuō)明 0x8badf00d 在啟動(dòng)、終?止應(yīng)?用或響應(yīng)系統(tǒng)事件花費(fèi)過(guò)?長(zhǎng)時(shí)間,意為“ate bad food”。 0xdeadfa11 ?用戶(hù)強(qiáng)制退出,意為“dead fall”勾扭。(系統(tǒng)?無(wú)響應(yīng)時(shí),?用戶(hù)按電源開(kāi)關(guān)和HOME) 0xbaaaaaad ?用戶(hù)按住Home鍵和?音量鍵,獲取當(dāng)前內(nèi)存狀態(tài),不代表崩潰 0xbad22222 VoIP應(yīng)?用因?yàn)榛謴?fù)得太頻繁導(dǎo)致crash 0xc00010ff 因?yàn)樘珷C了被干掉,意為“cool off” 0xdead10cc 因?yàn)樵诤笈_(tái)時(shí)仍然占據(jù)系統(tǒng)資源(?比如通訊錄)被干掉,意為“dead lock”

以上為摘抄內(nèi)容,僅供自己收藏使用。
原文地址:http://www.2cto.com/kf/201609/547867.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市怪瓶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敛滋,老刑警劉巖蜜唾,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咱揍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡且蓬,警方通過(guò)查閱死者的電腦和手機(jī)恶阴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人版述,你說(shuō)我怎么就攤上這事晚伙。” “怎么了俭茧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵咆疗,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我母债,道長(zhǎng)午磁,這世上最難降的妖魔是什么尝抖? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮迅皇,結(jié)果婚禮上昧辽,老公的妹妹穿的比我還像新娘。我一直安慰自己登颓,他們只是感情好搅荞,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著挺据,像睡著了一般取具。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扁耐,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天暇检,我揣著相機(jī)與錄音,去河邊找鬼婉称。 笑死块仆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的王暗。 我是一名探鬼主播悔据,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼俗壹!你這毒婦竟也來(lái)了科汗?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤绷雏,失蹤者是張志新(化名)和其女友劉穎头滔,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體涎显,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坤检,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了期吓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片早歇。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖讨勤,靈堂內(nèi)的尸體忽然破棺而出箭跳,到底是詐尸還是另有隱情,我是刑警寧澤潭千,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布衅码,位于F島的核電站,受9級(jí)特大地震影響脊岳,放射性物質(zhì)發(fā)生泄漏逝段。R本人自食惡果不足惜垛玻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奶躯。 院中可真熱鬧帚桩,春花似錦、人聲如沸嘹黔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)儡蔓。三九已至郭蕉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間喂江,已是汗流浹背召锈。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留获询,地道東北人涨岁。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吉嚣,于是被迫代替她去往敵國(guó)和親梢薪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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

  • 盡管當(dāng)iphone應(yīng)用崩潰時(shí)尝哆,它不會(huì)告訴用戶(hù)發(fā)生了什么秉撇,但我們?nèi)匀豢梢詾閼?yīng)用添加異常和信號(hào)處理,以此記錄和展示發(fā)生...
    韌卓閱讀 1,928評(píng)論 1 6
  • 文章目錄 一. 系統(tǒng)Crash 二. 處理signal 下面是一些信號(hào)說(shuō)明 關(guān)鍵點(diǎn)注意 三. 實(shí)戰(zhàn) 四. Cras...
    MTDeveloper閱讀 1,157評(píng)論 1 2
  • 最近這篇一年以前的文章秋泄,遭到了別人的嘲諷琐馆,本篇的初衷就是自己記錄,測(cè)試也僅僅使用了數(shù)組越界來(lái)玩過(guò)印衔,內(nèi)容可能比較單薄...
    190CM閱讀 5,344評(píng)論 8 8
  • 這本書(shū)我聽(tīng)了好幾遍,但是到這兒姥敛,我理不清分支和關(guān)鍵詞奸焙,如何往下理,我還要再聽(tīng)聽(tīng)彤敛。
    qianqifang閱讀 82評(píng)論 0 0
  • 夜飲 夜雨霏霏 霓虹不經(jīng) 縷縷春寒 今夜 且背倚嘉陵江 佯裝賓客的中唐 劍舞玉鉤垂 筆走二月天 呼出放免...
    張綱閱讀 353評(píng)論 0 2