一、什么情况下会产生崩溃日志?
两种主要情况会产生崩溃日志:
1.应用违反操作系统规则。
2.应用中有Bug。
违反iOS规则包括在启动、恢复、挂起、退出时watchdog超时、用户强制退出和低内存终止。
Watchdog 超时机制
从iOS 4.x开始,退出应用时,应用不会立即终止,而是退到后台。但是,如果你的应用响应不够快,操作系统有可能会终止你的应用,并产生一个崩溃日志。这些事件与下列UIApplicationDelegate方法相对应:
application:didFinishLaunchingWithOptions:
applicationWillResignActive:
applicationDidEnterBackground:
applicationWillEnterForeground:
applicationDidBecomeActive:
applicationWillTerminate:
上面所有这些方法,应用只有有限的时间去完成处理。如果花费时间太长,操作系统将终止应用。
注意: 如果你没有把需要花费时间比较长的操作(如网络访问)放在后台线程上就很容易发生这种情况。关于如果避免这种情况的信息,可采用: Grand Central Dispatch 和 NSOperations。
用户强制退出
iOS 4.x开始支持多任务。如果应用阻塞界面并停止响应, 用户可以通过在主屏幕上双击Home按钮来终止应用。此时,操作应用将生成一个崩溃日志。
注意: 双击Home按钮后,你将看到运行过的所有应用。那些应用不一定是正在运行,也不一定是被挂起。
通常,用户点击Home按钮时,应用将在后台保留约10分钟,然后操作系统自动将其终止。 所以双击Home按钮显示的应用列表只是表明那是一系列过去打开过的应用。删除那些应用的图标不会产生任何崩溃日志。
低内存终止
子类化UIViewController时,你或许已经注意到didReceiveMemoryWarning方法。
在前台运行的应用拥有访问和使用内存的最高优化级。然而,这并不意味着该应用能使用设备的所有可用内存 —— 每个应用只能使用一部分可用内存。
当内存使用达到一定程度时,操作系统将发出一个 UIApplicationDidReceiveMemoryWarningNotification 通知。同时,调用 didReceiveMemoryWarning 方法。
此时,为了让应用继续正常运行,操作系统开始终止在后台的其他应用以释放一些内存。所有后台应用被终止后,如果你的应用还需要更多内存,操作系统会将你的应用也终止掉,并产生一个崩溃日志。而在这种情况下被终止的后台应用,不会产生崩溃日志。
注意: 根据 苹果文档, Xcode不会自动添加低内存日志。你必需手动获取日志。 然而,根据我的个人经验,使用 Xcode 4.5.2, 低内存日志也会自动导入,只是”Process”和”Type”属性都被标为Unknown(未知)。
另外,值得一提的是在极短时间内分配一大块内存将给系统内存带来巨大负担。这样,也会产生内存警告的通知。
应用中有Bug
如你所想,大多数闪退都是由于应用中有Bug,因此大多数崩溃日志的产生都是因为应用中的Bug。Bug的种类的有很多。
二、崩溃的收集方式:
【1】:直接可以拿到设备。
iOS设备上的应用闪退时,操作系统会生成一个崩溃报告,也叫崩溃日志,保存在设备上。
有几种方法可以从设备上获取崩溃日志。
设备与电脑上的iTunes Store同步后,会将崩溃日志保存在电脑上。根据电脑操作系统的不同,崩溃日志将保存在以下位置:
Mac OS X:~/Library/Logs/CrashReporter/MobileDevice/
Windows XP: C:Documents and Settings<USERNAME>Application DataApple ComputerLogsCrashReporterMobileDevice<DEVICE_NAME>
Windows Vista or 7: C:Users<USERNAME>AppDataRoamingApple ComputerLogsCrashReporterMobileDevice<DEVICE_NAME>
如果有Xcode。从菜单栏上选择 Window 菜单, 然后选择 Organizer (快捷方式是 Shift-CMD-2)。
在 Organizer 窗口上, 选中 Devices 标签栏. 在左侧的导航面板上,选中 Device Logs。
左侧有好几个 Device Logs 菜单项。 LIBRARY 下面的Device Logs是你所有设备(曾经连接到Xcode的)的日志 。每个设备下面的 Device Logs 是对应设备的日志。
【2】.xcode中查看崩溃信息
xcode->Window->Organizer->Crashes
【3】:已经上线的应用通过 itunesconnect。
登录到 iTunes Connect 上, 选择 Manage Your Applications, 点击相应的应用, 点击应用图标下面的 View Details 按钮, 然后点击右栏Links部分的 Crash Reports 。
如果没有崩溃日志,试试点击Refresh 按钮刷新一下。如果你的应用还卖得不多,或者刚上架不久,iTunes Connect账号上也可能还没有任何崩溃日志。
【4】:符号表文件 dsYM 解析法:如果app 里面自己写了代码 保存崩溃的信息,提交服务器后可以获取崩溃后 堆栈的信息。
符号表就是指在Xcode项目编译后,在编译生成的二进制文件.app的同级目录下生成的同名的.dSYM文件。
.dSYM文件其实是一个目录,在子目录中包含了一个16进制的保存函数地址映射信息的中转文件,所有Debug的symbols都在这个文件中(包括文件名、函数名、行号等),所以也称之为调试符号信息文件。
dsYM 获取方式:
1.(蓝色选中的 就是archieves上传到 appStore 的包)鼠标右击 -> show in Finder -> 显示包内容 可以看到 名字为 “dSYMs”的文件夹,里面和工程同名的就是自己工程的符号表文件。
2. 此外既然曾经提交的时候在iTunesconnect 构建过版本,那就还可以从 iTunesconnect 获取,找到对应版本 app “活动” 的记录,看看是否有dsYM。
建议以后APP提交上传后,不要删除Archives 里面上传的包,默认保留起来就好。
【5】(可接入 第三方sdk, 如友盟崩溃分析,腾讯的bugly 等)收集bug 统计崩溃率,定位函数等,就方便多了。
三、异常信息解读
【1】:一种是很直接非常简单, 可以直接 根据 符号表文件 dsYM 分析出 崩溃到自己写的代码的地方,并定位到函数的。
【2】:难度高一些的 如:Exception Type(异常类型)
异常类型 | 可能的原因 | 调试方法 |
EXC_CRASH |
unrecognized selector |
All Exception Point |
EXC_BAD_ACCESS |
内存访问错误 |
NSZombie |
SIGSEGV |
引用了released对象 / 引用未init的对象 / 数组越界/ 试图往没有写权限的内存地址写数据 |
NSZombie |
SIGABRT |
逻辑错误导致的Crash,比如尝试多次释放同一个没存 |
逻辑检查 |
SIGPIPE |
TCP突然断开,再发送数据 |
添加signal(SIGPIPE,XX) |
具体信号说明参见iOS异常捕获:
http://www.iosxxx.com/blog/2015-08-29-iosyi-chang-bu-huo.html
【2】:难度高一些的 还有:Exception Type(异常类型)
异常编码 | 描述 |
0x8badf00d |
ate bad food ,表示应用是因为发生watchdog超时而被iOS终止的。通常是应用花费太多时间而无法启动、终止或响应用系统事件。 |
0xdeadfa11 |
dead fall,用户强制退出。 |
0xbaaaaaad |
用户按住Home键和音量键,获取当前内存状态,不代表崩溃。 |
0xbad22222 |
VoIP 应用因为过于频繁重启而被终止 |
0xc00010ff |
cool off,因为太烫了被干掉 |
0xdead10cc |
dead lock,表明应用因为在后台运行时占用系统资源(如通讯录数据库) |
0xbbadbeef |
bad beef,发生致命错误 |
说明1:详细的异常编码代表的含义请参考:Hexspeak。
说明2:在后台任务列表中关闭已挂起的应用不会产生崩溃日志。 因为应用一旦被挂起,它何时被终止都是合理的。所以不会产生崩溃日志。