在iOS開發(fā)中經(jīng)常需要靠記錄日志來調(diào)試應(yīng)用程序、解決崩潰問題等坐梯,整理常用的日志輸出和崩潰日志分析。
最新更新:2018-11-30
基于CocoaLumberjack 的 Swift使用封裝庫
一瓤逼、崩潰的捕獲
1勺馆、崩潰日志產(chǎn)生原因
1、應(yīng)用中有Bug拗秘。
2圣絮、Watchdog 超時機制
3、用戶強制退出
4雕旨、低內(nèi)存終止
5扮匠、其他違反系統(tǒng)規(guī)則的操作,大部分是內(nèi)存問題
發(fā)生崩潰奸腺,系統(tǒng)會生成一份崩潰日志在本地餐禁,或者上傳 ITC
2、崩潰的類型(異常突照、信號錯誤)
異常類
NSRangeException等 NSException類
信號錯誤類
信號中斷(SGIABRT)、非法指令信號(SIGILL)氧吐、總線錯誤信號(SIGBUS)讹蘑、段錯誤信號(SIGSEGV)末盔、訪問一個已經(jīng)釋放的對象(EXC_BAD_ACCESS)
3、捕獲異常崩潰信息
只能捕獲一些異常崩潰座慰,如 unrecognized selector陨舱、NSRangeException beyond bounds越界等Exception屬錯誤
Appdelegate
在Appdelegate 的 didFinishLaunchingWithOptions 中 添加
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
方法實現(xiàn)如下
void UncaughtExceptionHandler(NSException *exception) {
/**
* 獲取異常崩潰信息
*/
NSArray *callStack = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSString *content = [NSString stringWithFormat:@"========異常錯誤報告========\nname:%@\nreason:\n%@\ncallStackSymbols:\n%@",name,reason,[callStack componentsJoinedByString:@"\n"]];
//將崩潰信息持久化在本地,下次程序啟動時版仔、或者后臺游盲,將崩潰信息作為日志發(fā)送給開發(fā)者。
[[NSUserDefaults standardUserDefaults] setObject:content forKey:@"ExceptionContent"];
}
測試
數(shù)組越界錯誤
NSMutableArray *array = [NSMutableArray array];
NSLog(@"%@",array[1]);
4蛮粮、捕獲信號錯誤崩潰信息
信號類型崩潰捕獲益缎,測試的時候如果測試Signal類型的崩潰,不要在xcode下的debug模式進行測試然想。因為系統(tǒng)的debug會優(yōu)先去攔截莺奔。應(yīng)該build好應(yīng)用之后直接點擊運行app進行測試。
1变泄、什么是信號
在計算機科學中令哟,信號(英語:Signals)是Unix、類Unix以及其他POSIX兼容的操作系統(tǒng)中進程間通訊的一種有限制的方式妨蛹。它是一種異步的通知機制屏富,用來提醒進程一個事件已經(jīng)發(fā)生。當一個信號發(fā)送給一個進程蛙卤,操作系統(tǒng)中斷了進程正常的控制流程狠半,此時,任何非原子操作都將被中斷表窘。如果進程定義了信號的處理函數(shù)典予,那么它將被執(zhí)行,否則就執(zhí)行默認的處理函數(shù)乐严。
在iOS中就是未被捕獲的Objective-C異常(NSException)瘤袖,導致程序向自身發(fā)送了SIGABRT信號而崩潰。
SIGABRT–程序中止命令中止信號
SIGALRM–程序超時信號
SIGFPE–程序浮點異常信號
SIGILL–程序非法指令信號
SIGHUP–程序終端中止信號
SIGINT–程序鍵盤中斷信號
SIGKILL–程序結(jié)束接收中止信號
SIGTERM–程序kill中止信號
SIGSTOP–程序鍵盤中止信號
SIGSEGV–程序無效內(nèi)存中止信號
SIGBUS–程序內(nèi)存字節(jié)未對齊中止信號
SIGPIPE–程序Socket發(fā)送失敗中止信號
2昂验、捕獲方法
Appdelegate 的 didFinishLaunchingWithOptions 中 添加
signal(SIGHUP, SignalHandler);
signal(SIGINT, SignalHandler);
signal(SIGQUIT, SignalHandler);
signal(SIGABRT, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGSEGV, SignalHandler);
signal(SIGFPE, SignalHandler);
signal(SIGBUS, SignalHandler);
signal(SIGPIPE, SignalHandler);
方法實現(xiàn)如下
void SignalHandler(int signal){
int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount > UncaughtExceptionMaximum)
{
return;
}
void* callstack[128];
int frames = backtrace(callstack, 128);
char **strs = backtrace_symbols(callstack, frames);
int i;
NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
for (
i = UncaughtExceptionHandlerSkipAddressCount;
i < UncaughtExceptionHandlerSkipAddressCount +
UncaughtExceptionHandlerReportAddressCount;
i++)
{
[backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
}
free(strs);
NSLog(@"%@",backtrace);
NSLog(@"%@", [NSString stringWithFormat:
NSLocalizedString(@"Signal %d was raised.", nil),
signal]);
}
3捂敌、測試
UIView *tempView = [[UIView alloc]init];
[tempView release];
//對象已經(jīng)被釋放,內(nèi)存不合法既琴,此塊內(nèi)存地址又沒被覆蓋占婉,所以此內(nèi)存內(nèi)垃圾內(nèi)存,所以調(diào)用方法的時候會導致SIGSEGV的錯誤
[tempView setNeedsDisplay];
或者說 我在堆內(nèi)存中找棧內(nèi)存地址
id x_id = [self performSelector:@selector(createNum)];
- (int)createNum {
return 10;
}
這種情況也是會導致SIGSEGV的錯誤的
如果在內(nèi)存中釋放不存在的空間甫恩,就會導致SIGABRT錯誤
Test * test = {1, 2};
free(test);
內(nèi)存地址不對齊會導致SIGBUS錯誤
char *s = "hello world";
*s = 'H';
4逆济、問題
信號捕獲后 app卡死了
大部分這類型的錯誤會報錯 EXC_BAD_ACCESS ,而這種錯誤都是發(fā)生在內(nèi)存問題,例如
1奖慌、訪問數(shù)據(jù)為空抛虫、數(shù)據(jù)類型不對
2、操作了不該操作的對象简僧,野指針
5建椰、EXC_BAD_ACCESS錯誤的調(diào)試
1、xcode可以用僵尸模式打印出對象 然后通過對象查找對應(yīng)的代碼位置
1岛马、Edit Scheme - Diagnositics - Memory Management 勾選 Zombie Objects 和 Malloc Stack
2棉姐、會打印出
cyuyan[7756:17601127] *** -[UIViewController respondsToSelector:]: message sent to deallocated instance 0x7fe71240d390
這句開啟僵尸模式后打出來的輸出,包含了我們需要的 進程pid啦逆、崩潰地址伞矩,終端通過下面命令查看堆棧日志來找到崩潰代碼
3、查找日志
sudo malloc_history 7756 0x7fe71240d390
2蹦浦、覆寫一個object的respondsToSelector方法
在 other c flags中加入-D FOR_DEBUG(記住請只在Debug Configuration下加入此標記)扭吁。這樣當你程序崩潰時,Xcode的console上就會準確地記錄了最后運行的object的方法盲镶。重寫一個object的respondsToSelector方法侥袜,打印報錯前的
#ifdef _FOR_DEBUG_
-(BOOL) respondsToSelector:(SEL)aSelector {
printf("SELECTOR: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
#endif
3、通過instruments的Zombies
引申:怎么定位到野指針的地方溉贿。如果還沒定位到枫吧,這個對象被提前釋放了,怎么知道該對象在什么地方釋放的
一種是多線程宇色,一種是野指針九杂。這兩種Crash都帶隨機性,我們要讓隨機crash變成不隨機
把這一隨機的過程變成不隨機的過程宣蠕。對象釋放后在內(nèi)存上填上不可訪問的數(shù)據(jù)例隆,其實這種技術(shù)其實一直都有,xcode的Enable Scribble就是這個作用抢蚀。
1镀层、Edit Scheme - Diagnositics - Memory Management 勾選 Malloc Scribble
但是此方法測試后暫時未解決
6、可能崩潰的一些場景
1皿曲、野指針
1唱逢、對象釋放后內(nèi)存沒被改動過,原來的內(nèi)存保存完好屋休,可能不Crash或者出現(xiàn)邏輯錯誤(隨機Crash)坞古。
2、對象釋放后內(nèi)存沒被改動過劫樟,但是它自己析構(gòu)的時候已經(jīng)刪掉某些必要的東西痪枫,可能不Crash织堂、Crash在訪問依賴的對象比如類成員上、出現(xiàn)邏輯錯誤(隨機Crash)听怕。
3捧挺、對象釋放后內(nèi)存被改動過虑绵,寫上了不可訪問的數(shù)據(jù)尿瞭,直接就出錯了很可能Crash在objc_msgSend上面(必現(xiàn)Crash,常見)翅睛。
4声搁、對象釋放后內(nèi)存被改動過,寫上了可以訪問的數(shù)據(jù)捕发,可能不Crash疏旨、出現(xiàn)邏輯錯誤、間接訪問到不可訪問的數(shù)據(jù)(隨機Crash)扎酷。
5檐涝、對象釋放后內(nèi)存被改動過,寫上了可以訪問的數(shù)據(jù)法挨,但是再次訪問的時候執(zhí)行的代碼把別的數(shù)據(jù)寫壞了谁榜,遇到這種Crash只能哭了(隨機Crash,難度大凡纳,概率低)G灾病!
6荐糜、對象釋放后再次release(幾乎是必現(xiàn)Crash巷怜,但也有例外,很常見)暴氏。
2延塑、內(nèi)存處理不當、內(nèi)存泄露
3答渔、主線程UI長時間卡死关带,系統(tǒng)強制銷毀app
死鎖?
4研儒、多線程切換訪問引起的crash
多線程搶寫數(shù)據(jù)庫豫缨?
5、和服務(wù)端約定的數(shù)據(jù)結(jié)構(gòu)變更導致操作數(shù)據(jù)類型問題端朵、或者操作空
二好芭、崩潰日志的獲取
1、iOS設(shè)備可以直接查看
路徑:
ios 10之后:設(shè)置 -> 隱私 -> 分析 -> 數(shù)據(jù)分析
ios 10之前:設(shè)置 -> 隱私 -> 診斷與用量
2冲呢、鏈接設(shè)備到電腦 Itunes同步后舍败,日志會保存在電腦上
mac路徑:~/Library/Logs/CrashReporter/MobileDevice/
可以看到所有和該電腦同步過的設(shè)備的崩潰日志(.crash文件)
為什么有部分crash無法收集到?
3、xcode獲取
xcode查看設(shè)備日志并導出日志
Window - Devices - 選擇設(shè)備 - 點擊View Device Logs -> All logs可以看到所有的崩潰日志邻薯。
4裙戏、線上的崩潰,沒有設(shè)備
1厕诡、三方:bugly累榜、crashlytics
2、后臺灵嫌、異步線程將上面描述的捕獲到的崩潰上傳服務(wù)器
3壹罚、線上的ITC上可能會有部分日志,可以通過Xcode同步下來崩潰與能耗日志
Xcode Window - Organizer - Crashes
三寿羞、崩潰日志的解析
1猖凛、崩潰日志的實例
下面是一份測試過程產(chǎn)生的崩潰日志
//進程信息
Incident Identifier: 3C3F8BF8-3099-4E82-92E1-8690212E8FF9
CrashReporter Key: bb5f9839ae661ab755f25eff65fee8fd41369628
Hardware Model: iPod5,1
Process: demo [973]
Path: /private/var/containers/Bundle/Application/0D3657DE-DE1E-4FF0-A0F7-C09EBC002763/demo.app/demo
Identifier: com.yanghuang.demo
Version: 17 (1.1.9)
Code Type: ARM (Native)
Parent Process: launchd [1]
//基本信息
Date/Time: 2017-08-22 16:11:49.49 +0800
Launch Time: 2017-08-22 16:11:40.40 +0800
OS Version: iOS 9.3.5 (13G36)
Report Version: 104
//異常
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000000e7ffdefe
Triggered by Thread: 0
Filtered syslog:
None found
//線程回溯
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libswiftCore.dylib 0x0033788c 0x1ac000 + 1620108
1 ...wiftSwiftOnoneSupport.dylib 0x009b4830 0x9ac000 + 34864
2 demo 0x00029288 0x24000 + 21128
3 demo 0x00029414 0x24000 + 21524
4 UIKit 0x25cd2754 0x25c87000 + 309076
5 UIKit 0x25cd26e0 0x25c87000 + 308960
6 UIKit 0x25cba6d2 0x25c87000 + 210642
7 UIKit 0x25cd2004 0x25c87000 + 307204
8 UIKit 0x25cd1c7e 0x25c87000 + 306302
9 UIKit 0x25cca68e 0x25c87000 + 276110
10 UIKit 0x25c9b124 0x25c87000 + 82212
11 UIKit 0x25c996d2 0x25c87000 + 75474
12 CoreFoundation 0x216e1dfe 0x21626000 + 769534
13 CoreFoundation 0x216e19ec 0x21626000 + 768492
14 CoreFoundation 0x216dfd5a 0x21626000 + 761178
15 CoreFoundation 0x2162f228 0x21626000 + 37416
16 CoreFoundation 0x2162f014 0x21626000 + 36884
17 GraphicsServices 0x22c1fac8 0x22c16000 + 39624
18 UIKit 0x25d03188 0x25c87000 + 508296
19 demo 0x0002ff48 0x24000 + 48968
20 libdyld.dylib 0x212d7872 0x212d5000 + 10354
Thread 1 name: Dispatch queue: com.apple.libdispatch-manager
Thread 1:
0 libsystem_kernel.dylib 0x213ac2f8 0x21396000 + 90872
1 libdispatch.dylib 0x212a1d60 0x2128b000 + 93536
2 libdispatch.dylib 0x212a1abe 0x2128b000 + 92862
... 省略部分內(nèi)容
//二進制映像
Binary Images
0x24000 - 0x33fff demo armv7 <aa31c8c1f8cb333596dbfe056b120673> /var/containers/Bundle/Application/0D3657DE-DE1E-4FF0-A0F7-C09EBC002763/demo.app/demo
0x140000 - 0x15bfff Masonry armv7 <9615e97c54d335f7821568396c65d324> /var/containers/Bundle/Application/0D3657DE-DE1E-4FF0-A0F7-C09EBC002763/demo.app/Frameworks/Masonry.framework/Masonry
1.進程信息
第一部分是閃退進程的相關(guān)信息。
Incident Identifier 是崩潰報告的唯一標識符绪穆。
CrashReporter Key 是與設(shè)備標識相對應(yīng)的唯一鍵值辨泳。雖然它不是真正的設(shè)備標識符,但也是一個非常有用的情報:如果你看到100個崩潰日志的CrashReporter Key值都是相同的玖院,或者只有少數(shù)幾個不同的CrashReport值菠红,說明這不是一個普遍的問題,只發(fā)生在一個或少數(shù)幾個設(shè)備上司恳。
Hardware Model 標識設(shè)備類型途乃。 如果很多崩潰日志都是來自相同的設(shè)備類型,說明應(yīng)用只在某特定類型的設(shè)備上有問題扔傅。上面的日志里耍共,崩潰日志產(chǎn)生的設(shè)備是iPhone 4s。
Process 是應(yīng)用名稱猎塞。中括號里面的數(shù)字是閃退時應(yīng)用的進程ID试读。
2.基本信息
這部分給出了一些基本信息,包括閃退發(fā)生的日期和時間荠耽,設(shè)備的iOS版本钩骇。如果有很多崩潰日志都來自iOS 6.0,說明問題只發(fā)生在iOS 6.0上铝量。
Version: 崩潰進程的版本號. 這個值包含在 CFBundleVersion and CFBundleVersionString中.
Code Type: 崩潰日志所在設(shè)備的架構(gòu). 會是ARM-64, ARM, x86-64, or x86中的一個.
OS Version: 崩潰發(fā)生時的系統(tǒng)版本
3.異常信息
異常信息會列出異常的類型倘屹、位置。
在這部分慢叨,你可以看到閃退發(fā)生時拋出的異常類型纽匙。還能看到異常編碼和拋出異常的線程。根據(jù)崩潰報告類型的不同拍谐,在這部分你還能看到一些另外的信息烛缔。
Exception Codes: 處理器的具體信息有關(guān)的異常編碼成一個或多個64位進制數(shù)馏段。通常情況下,這個區(qū)域不會被呈現(xiàn)践瓷,因為將異常代碼解析成人們可以看懂的描述是在其它區(qū)域進行的院喜。
Exception Subtype: 供人們可讀的異常代碼的名字
Exception Message: 從異常代碼中提取的額外的可供人們閱讀的信息.
Exception Note: 不是特定于一個異常類型的額外信息.如果這個區(qū)域包含SIMULATED (這不是一個崩潰)然后進程沒有崩潰,但是被watchdog殺掉了
Termination Reason: 當一個進程被終止的時的原因晕翠。
Triggered by Thread: 異常所在的線程.
4.線程回溯
這部分提供應(yīng)用中所有線程的回溯日志喷舀。 回溯是閃退發(fā)生時所有活動幀清單。它包含閃退發(fā)生時調(diào)用函數(shù)的清單崖面≡看下面這行日志:
2 demo 0x00029288 0x24000 + 21128
它包括四列:
幀編號—— 此處是2。
二進制庫的名稱 ——此處是 demo.
調(diào)用方法的地址 ——此處是 0x00029288.
第四列分為兩個子列巫员,一個基本地址和一個偏移量。此處是0×0x24000 + 21128, 第一個數(shù)字指向文件甲棍,第二個數(shù)字指向文件中的代碼行简识。
5.二進制映像
這部分列出了閃退時已經(jīng)加載的二進制文件。
2感猛、符號化Symbolication
第一次看到崩潰日志上的回溯時七扰,你或許會覺得它沒什么意義。我們習慣使用方法名和行數(shù)陪白,而非像這樣的神秘位置:
2 demo 0x00029288 0x24000 + 21128
將這些十六進制地址轉(zhuǎn)化成方法名稱和行數(shù)的過程稱之為符號化颈走。
從Xcode的Organizer窗口獲取崩潰日志后過幾秒鐘,崩潰日志將被自動符號化咱士。上面那行被符號化后的版本如下 :
2 demo 0x00029288 ViewController.crashAction(Any) -> () (ViewController.swift:36)
Xcode符號化崩潰日志時立由,需要訪問與App Store上對應(yīng)的應(yīng)用二進制文件以及生成二進制文件時產(chǎn)生的 .dSYM 文件。必需完全匹配才行序厉。否則锐膜,日志將無法被完全符號化。
所以弛房,保留每個分發(fā)給用戶的編譯版本非常重要道盏。提交應(yīng)用前進行歸檔時,Xcode將保存應(yīng)用的二進制文件文捶『沙眩可以在Xcode Organizer的Archives標簽欄下找到所有已歸檔的應(yīng)用文件。
在發(fā)現(xiàn)崩潰日志時粹排,如果有相匹配的.dSYM文件和應(yīng)用二進制文件种远,Xcode會自動對崩潰日志進行符號化。如果你換到別的電腦或創(chuàng)建新的賬戶恨搓,務(wù)必將所有二進制文件移動到正確的位置院促,使Xcode能找到它們筏养。
注意:
1、你必需同時保留應(yīng)用二進制文件和.dSYM文件才能將崩潰日志完整符號化常拓。每次提交到iTunes Connect的構(gòu)建都必需歸檔渐溶。 .dSYM文件和二進制文件是特定綁定于每一次構(gòu)建和后續(xù)構(gòu)建的,即使來自相同的源代碼文件弄抬,每一次構(gòu)建也與其他構(gòu)建不同茎辐,不能相互替換。如果你使用Build 和 Archive 命令,這些文件會自動放在適當位置掂恕。 如果不是使用Build 和 Archive命令拖陆,放在Spotlight能夠搜索到的位置(比如Home目錄)即可。
2懊亡、xcode debug方式打包默認沒有DSYM文件依啰,只需要修改對應(yīng)的build options即可
build settings -> build options
把debug 項改成 DWARF with dSYM File 即可
如何通過.crash文件反編譯得到明文的crash文件
需要文件:
1、demo.app
2店枣、demo.app.dSYM
3速警、demo.crash (已獲得)
4、symbolicatecrash
符號化前先檢查一下三者的uuid是不是一致的,只有是一致的才能符號化成功鸯两。
查看xx.app文件的uuid的方法:
dwarfdump --uuid xxx.app/xxx (xxx工程名)
查看xx.app.dSYM文件的uuid的方法令:
dwarfdump --uuid xxx.app.dSYM (xxx工程名)
而.crash的uuid位于闷旧,crash日志中的Binary Images:中的第一行尖括號內(nèi)。如:armv7<8bdeaf1a0b233ac199728c2a0ebb4165>
步驟如下:
1钧唐、首先我們找到Archives目錄(/Users/用戶名/Library/Developer/Xcode/Archives/2017-08-22/demo)
2忙灼、找到對應(yīng)app目錄、對應(yīng)的Archives文件钝侠、顯示包內(nèi)容打開该园。在dSYMs文件夾中找到demo.app.dSYM
在Products->Applications文件夾中找到 demo.app
3、找到symbolicatecrash
find /Applications/Xcode.app -name symbolicatecrash -type f
//終端輸入上面命令机错、得到一個路徑爬范,這個路徑就是symbolicatecrash的路徑
拷貝到和上面文件同一目錄
3: 在終端中輸入以下命令
./symbolicatecrash -v demo.crash demo.app.dSYM
如果出現(xiàn)Error: "DEVELOPER_DIR" is not defined 再執(zhí)行下面一句后再次執(zhí)行
export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"
然后用控制臺打開你的demo.crash文件, 你就會看到編譯后的crash文件, 同Xcode看到的崩潰日志一致。通過查看崩潰日志弱匪,可以輕易的找到崩潰原因并修正青瀑。
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libswiftCore.dylib 0x0033788c 0x1ac000 + 1620108
1 ...wiftSwiftOnoneSupport.dylib 0x009b4830 0x9ac000 + 34864
2 demo 0x00029288 ViewController.crashAction(Any) -> () (ViewController.swift:36)
3 demo 0x00029414 @objc ViewController.crashAction(Any) -> () (ViewController.swift:0)
4 UIKit 0x25cd2754 -[UIApplication sendAction:to:from:forEvent:] + 80
5 UIKit 0x25cd26e0 -[UIControl sendAction:to:forEvent:] + 64
6 UIKit 0x25cba6d2 -[UIControl _sendActionsForEvents:withEvent:] + 466
7 UIKit 0x25cd2004 -[UIControl touchesEnded:withEvent:] + 604
8 UIKit 0x25cd1c7e -[UIWindow _sendTouchesForEvent:] + 646
9 UIKit 0x25cca68e -[UIWindow sendEvent:] + 642
10 UIKit 0x25c9b124 -[UIApplication sendEvent:] + 204
11 UIKit 0x25c996d2 _UIApplicationHandleEventQueue + 5010
12 CoreFoundation 0x216e1dfe __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
13 CoreFoundation 0x216e19ec __CFRunLoopDoSources0 + 452
14 CoreFoundation 0x216dfd5a __CFRunLoopRun + 794
15 CoreFoundation 0x2162f228 CFRunLoopRunSpecific + 520
16 CoreFoundation 0x2162f014 CFRunLoopRunInMode + 108
17 GraphicsServices 0x22c1fac8 GSEventRunModal + 160
18 UIKit 0x25d03188 UIApplicationMain + 144
19 demo 0x0002ff48 main (AppDelegate.swift:13)
20 libdyld.dylib 0x212d7872 start + 2
3、低內(nèi)存閃退
因為低內(nèi)存崩潰日志與普通崩潰日志略有不同萧诫。
iOS設(shè)備檢測到低內(nèi)存時斥难,虛擬內(nèi)存系統(tǒng)發(fā)出通知請求應(yīng)用釋放內(nèi)存。這些通知發(fā)送到所有正在運行的應(yīng)用和進程帘饶,試圖收回一些內(nèi)存哑诊。
如果內(nèi)存使用依然居高不下,系統(tǒng)將會終止后臺線程以緩解內(nèi)存壓力及刻。如果可用內(nèi)存足夠镀裤,應(yīng)用將能夠繼續(xù)運行而不會產(chǎn)生崩潰報告竞阐。否則,應(yīng)用將被iOS終止暑劝,并產(chǎn)生低內(nèi)存崩潰報告骆莹。
低內(nèi)存崩潰日志上沒有應(yīng)用線程的堆棧回溯担猛。相反幕垦,上面顯示的是以內(nèi)存頁數(shù)為單位的各進程內(nèi)存使用量。
被iOS因釋放內(nèi)存頁終止的進程名稱后面你會看到j(luò)ettisoned 字樣傅联。如果看到它出現(xiàn)在你的應(yīng)用名稱后面先改,說明你的應(yīng)用因使用太多內(nèi)存而被終止了。
低內(nèi)存崩潰日志看起來像這樣:
4蒸走、異常編碼
通常仇奶,異常編碼以一些文字開頭,緊接著是一個或多個十六進制值载碌,此數(shù)值正是說明閃退根本性質(zhì)的所在猜嘱。 從這些編碼中,可以區(qū)分出閃退是因為程序錯誤嫁艇、非法內(nèi)存訪問或者是其他原因。
下面是一些常見的異常編碼:
0x8badf00d: 該編碼表示應(yīng)用是因為發(fā)生watchdog超時而被iOS終止的弦撩。 通常是應(yīng)用花費太多時間而無法啟動步咪、終止或響應(yīng)用系統(tǒng)事件。
0xbad22222: 該編碼表示 VoIP 應(yīng)用因為過于頻繁重啟而被終止益楼。
0xdead10cc: 該代碼表明應(yīng)用因為在后臺運行時占用系統(tǒng)資源猾漫,如通訊錄數(shù)據(jù)庫不釋放而被終止 。
0xdeadfa11: 該代碼表示應(yīng)用是被用戶強制退出的感凤。根據(jù)蘋果文檔, 強制退出發(fā)生在用戶長按開關(guān)按鈕直到出現(xiàn) “滑動來關(guān)機”, 然后長按 Home按鈕悯周。強制退出將產(chǎn)生 包含0xdeadfa11 異常編碼的崩潰日志, 因為大多數(shù)是強制退出是因為應(yīng)用阻塞了界面。
EXC_CRASH // SIGABRT: 進程異常退出陪竿。該異常類型崩潰最常見的原因是未捕獲的Objective-C和C++異常和調(diào)用abort()禽翼。如果他們需要太多的時間來初始化,程序?qū)⒈唤K止族跛,因為觸發(fā)了看門狗闰挡。如果是因為啟動的時候被掛起,所產(chǎn)生的崩潰報告異常類型(Exception Subtype)將是launch_hang礁哄。
EXC_BREAKPOINT // SIGTRAP:進程試圖執(zhí)行非法或未定義指令长酗。這個進程可能試圖通過一個配置錯誤的函數(shù)指針,跳到一個無效的地址桐绒。
SIGSEGV夺脾、SIGBUS 這些在前面捕獲異常的內(nèi)容有描述
注意: 在后臺任務(wù)列表中關(guān)閉已掛起的應(yīng)用不會產(chǎn)生崩潰日志之拨。 一旦應(yīng)用被掛起,它何時被終止都是合理的咧叭。所以不會產(chǎn)生崩潰日志蚀乔。
四、線上問題的處理
思考:
1佳簸、工作中是否有遇到過線上反饋回來的問題乙墙,你是如何定位問題處理的
2、如果有特殊賬戶才出現(xiàn)的問題生均,但是又拿不到用戶賬戶听想,該如何處理