方案1:NSZombieEnabled
先選中工程, 依次 "Product"-"Edit Scheme", 左欄選擇"Run...", 右欄選中Arguments, 然後在Environment Variables下面添加以下三個屬性, 設值為YES
NSDebugEnabled
NSZombieEnabled
NSAutoreleaseFreedObjectCheckEnabled
有時候在程式出錯的時候能準確定位到奔潰的那一行, 或者會給你下面這樣的提示,而不僅僅是EXEC_BAD_ACCESS:
message sent to deallocated instance 0x126550
如果要查看上面地址的分配情況
開啟MallocStackLogging(Xcode4勾選下MallocStackLogging就行)
出錯時shell malloc_history pid address
另:有時候可以重載respondsToSelector可以幫你找到程式崩潰時最後執行的函數,然後排查.
方案2:添加全域斷點
Xcode4可以很方便的添加全域的異常斷點
方案3:中斷和未捕獲異常
1.未攔截訊號來源:核心,其他程式,本身.
常見的兩個訊號:
1).EXC_BAD_ACCESS 試圖訪問非法記憶體,導致SIGBUS或者SIGSEGV訊號
2).未能攔截obj_exception_throw導致的SIGABRT訊號.
2.方法
1).使用NSUncaughtionHandler安裝一個handler攔截未攔截異常
2).使用signal函數安裝一個handler攔截BSD訊號.(SIGKILL[kill -9]和SIGSTOP[Control+z]無法攔截)
兩個c函數
void SignalHandler(int signal){//中斷訊號}void uncaughtExceptionHandler(NSException *exception){//未捕獲異常}
安裝(與全域異常斷點衝突,當有這樣的斷點是,下面攔截函數失效)
void InstallUncaughtExceptionHandler(){ NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); signal(SIGABRT, SignalHandler); signal(SIGILL, SignalHandler); signal(SIGSEGV, SignalHandler); signal(SIGFPE, SignalHandler); signal(SIGBUS, SignalHandler); signal(SIGPIPE, SignalHandler);}
3.具體執行個體
1.http://cocoawithlove.com/2010/05/handling-unhandled-exceptions-and.html
重點在於嘗試繼續運行程式
告訴使用者那些因為這些未攔截的異常和訊號導致的崩潰,或者自己記錄,甚至可以避開這樣導致的崩潰.不過,如果多個訊號攔截了,這可能失效.
非常推薦看看這篇文章
2.http://parveenkaler.com/2010/08/11/crashkit-helping-your-iphone-apps-suck-less/
重點在於記錄異常(之後返回主線程)
- (void)pumpRunLoop{ self.finishPump = NO; CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFArrayRef runLoopModesRef = CFRunLoopCopyAllModes(runLoop); NSArray * runLoopModes = (NSArray*)runLoopModesRef; while (self.finishPump == NO) { for (NSString *mode in runLoopModes) { CFStringRef modeRef = (CFStringRef)mode; CFRunLoopRunInMode(modeRef, 1.0f/120.0f, false); // Pump the loop at 120 FPS } } CFRelease(runLoopModesRef);}