在ios开发过程,当应用已经打包,iPhone设备通过ipa的包安装应用后,在使用过程发现crash,那么如何获取crash日志呢,现提供如下四种获取crash日志的方式:
1、打开iPhone设备的设置里面的隐私中的“诊断与用量”,然后如果app崩溃了,设备会弹出提示框,用户确认之后,crash log会自动发送到苹果后台,然后用开发者账号登陆上去,可以拿到crash log。
2、将设备链接到mac或者windows上,同步到iTunes后再从电脑的目录下获取crash log:
Mac OS X:~/Library/Logs/CrashReporter/MobileDevice
Windows XP:C:\Documents and Settings\Application Data\Apple computer\Logs\CrashReporter
Windows 7/Vista: C:\Users\计算机登录名\AppData\Roaming\Apple Computer\Logs\CrashReporter\MobileDevice
3、可以通过itools工具获取crash log,打开itools,连接iPhone设备,按照下图提示,获取crash log
4、通过xcode获取crash log,打开xcode,连接iPhone设备,打开window下的device,可以看到你连接的设备,可以看到如下界面,点击view device logs,可以看到所有的日志,选中日志,点击右键可以到处日志
二、解析crash logs
经网上搜索解析crash logs的三种,由于未经测试,所以没有记录下,详见可以:http://www.cocoachina.com/industry/20140514/8418.html
经测试可用的方法为atos -o XXX.app.dSYM/Contents/Resources/DWARF/XXX -l address0 targetAddress
其中:
a、XXX是appname
b、address0是当前进程在内存中加载的起始地址,至于为什么需要这个,那就有必要去了解下ASLR
获取地址参下图:
binary Images后面第一个即为基地址(内存中加载的起始地址)
c、targetAddress就是你想要符号化的地址 ,此处一般选取如下
3 appName 0x000f462a 0x4000 + 984618
4 appName 0x00352aee 0x4000 + 3468014
以appName开头的地址
二、常见的Crash类型
1、Watchdog timeout
Exception Code:0x8badf00d, 不太直观,可以读成“eat bad food”,意思是don‘t block main thread
紧接着下面会有一段描述:
Application Specific Information:
com.xxx.yyy failed to resume in time
对于此类Crash,我们应该去审视自己App初始化时做的事情是否正确,是否在主线程请求了网络,或者其他耗时的事情卡住了正常初始化流程。
通常系统允许一个App从启动到可以相应用户事件的时间最多为5S,如果超过了5S,App就会被系统终止掉。在Launch,resume,suspend,quit时都会有相应的时间要求。在Highlight Thread里面我们可以看到被终止时调用到的位置,xxxAppDelegate加上行号。
PS. 在连接Xcode调试时为了便于调试,系统会暂时禁用掉Watchdog,所以此类问题的发现需要使用正常的启动模式。
2、User force-quit
Exception Codes: 0xdeadfa11, deadfall
这个强制退出跟我们平时所说的kill掉后台任务操作还不太一样,通常在程序bug造成系统无法响应时可以采用长按电源键,当屏幕出现关机确认画面时按下Home键即可关闭当前程序。
3、Low Memory termination
跟一般的Crash结构不太一样,通常有Free pages,Wired Pages,Purgeable pages,largest process 组成,同事会列出当前时刻系统运行所有进程的信息。
关于Memory warning可以参看我之前写的一篇文章IOS 内存警告 Memory warning level。
App在运行过程中,系统内存紧张时通常会先发警告,同时把后台挂起的程序终止掉,最终如果还是内存不够的话就会终止掉当前前台的进程。
当接受到内存警告的事后,我们应该释放尽可能多的内存,Crash其实也可以看做是对App的一种保护。
4、Crash due to bugs
因为程序bug导致的Crash通常千奇百怪,很难一概而论。大部分情况通过Crash日志就可以定位出问题,当然也不排除部分疑难杂症看半天都不值问题出在哪儿。这个就只能看功底了,一点点找,总是能发现蛛丝马迹。是在看不出来时还可以求助于Google大神,总有人遇到和你一样的Bug
三、常见的Exception Type & Exception Code
1、Exception Type
1)EXC_BAD_ACCESS
此类型的Excpetion是我们最长碰到的Crash,通常用于访问了不改访问的内存导致。一般EXC_BAD_ACCESS后面的"()"还会带有补充信息。
SIGSEGV: 通常由于重复释放对象导致,这种类型在切换了ARC以后应该已经很少见到了。
SIGABRT: 收到Abort信号退出,通常Foundation库中的容器为了保护状态正常会做一些检测,例如插入nil到数组中等会遇到此类错误。
SEGV:(Segmentation Violation),代表无效内存地址,比如空指针,未初始化指针,栈溢出等;
SIGBUS:总线错误,与 SIGSEGV 不同的是,SIGSEGV 访问的是无效地址,而 SIGBUS 访问的是有效地址,但总线访问异常(如地址对齐问题)
SIGILL:尝试执行非法的指令,可能不被识别或者没有权限
2)EXC_BAD_INSTRUCTION
此类异常通常由于线程执行非法指令导致
3)EXC_ARITHMETIC
除零错误会抛出此类异常