【iOS篇】从容面对App崩溃
有代码的地方,就可能会有崩溃。定位崩溃问题的方法:最直接的,通过重现的步骤去调适;但是,有时候测试无法确定崩溃的步骤,或者崩溃是线上用户发生的,这些情况下,我们仍然可以通过崩溃日志,知道崩溃的原因和崩溃的代码行,从而修复问题。
—— 什么是崩溃?
Application crashes: An applicationtypically crashes when it performs an operation which is not allowed by the operatingsystem.
Server crashes, Operating systemcrashes, …
——定位崩溃原因的方法有哪些?
线索1:重现步骤
线索2:崩溃日志(知道崩溃的原因、崩溃的代码行等信息)
那么,本文就来说说崩溃日志。
●●●
获取日志的几种方法
在iOS系统中,当应用崩溃的时候,系统会生成一个崩溃日志,保存在设备上。
1.直接在手机上查看
在手机端设置里查看,如图是iOS10的界面:
2.手机连PC用iTunes导出
iTunes同步资料库,然后去PC对应目录下,找文件
Mac OS X: ~/Library/Logs/CrashReporter/MobileDevice/
Windows XP: C://Documents andSettings/Application Data/Apple Computer/Logs/Crash/Reporter/MobileDevice
Windows Vista or 7: C://Users/AppData/Roaming/AppleComputer/Logs/Crash/Reporter/MobileDevice
3.手机连XCode导出
Simulator-Hardware-Device-ManageDevices
4.XCode中,对提交商店的应用,查看Crashes
xcode->Window->Organizer->Crashes
5.用iTunes Connect(提交商店的应用)
如果应用提交到App Store了,还可以从iTunes Connect(https://itunesconnect.apple.com/)上获取到用户的崩溃日志.。通过应用提交者的apple id登录,管理提交的应用,应用细节中有一个崩溃报告
5.app植入第三方sdk,配合第三方平台查看
很多第三方平台,(比如蒲公英、fabric、网易云捕...)提供sdk和管理后台。
只需要使用它们的sdk,并添加几行代码,app运行时,sdk会将应用Crash数据自动上传到后台,后台会进行相应的统计和分析。并给出产品各个版本的崩溃数,崩溃率,影响用户数,崩溃的机型、系统等。
6.使用苹果的api,自己实现抓取崩溃信息,提交到自己写的后台
和5是一样的,有这些现成的情况下,不是很必要自己重新再写一个,但是可以简单了解一下其中的关键原理。
1.iOS SDK中提供了一个现成的函数NSSetUncaughtExceptionHandler用来做异常处理。
voidHandleException(NSException*exception) //捕捉到异常时执行的方法
{
//异常的堆栈信息
NSArray*stackArray = [exceptioncallStackSymbols];
//出现异常的原因
NSString*reason = [exception reason];
//异常名称
NSString*name = [exception name];
NSString*exceptionInfo =[NSStringstringWithFormat:@"Exception reason:%@\nException name:%@\nExceptionstack:%@",name, reason, stackArray];
NSLog(@"%@",exceptionInfo);
[UncaughtExceptionHandlersaveCrash:exceptionInfo]; //自己实现一个记录下这些信息的方法,作者是实现了一个写文本文件的方法
}
voidInstallUncaughtExceptionHandler(void) //注册一些抓取函数,在APPDelegate中didFinishLaunchingWithOptions调用
{
NSSetUncaughtExceptionHandler(&HandleException);
}
2.但NSSetUncaughtExceptionHandler功能非常有限,而引起崩溃的原因如:内存访问错误,重复释放等错误并不能被抓到,而这种错误它抛出的是Signal,因此做一个Signal处理可以抓到这一类的崩溃。
voidSignalExceptionHandler(intsignal) //抓取到Signal异常时,执行的方法
{
NSMutableString*mstr =[[NSMutableString alloc] init];
[mstrappendString:@"Stack:\n"];
void* callstack[128];
inti, frames =backtrace(callstack,128);
char**strs =backtrace_symbols(callstack, frames);
for(i=0; i<frames;++i){
[mstr appendFormat:@"%s\n", strs[i]];
}
[SignalHandlersaveCrash:mstr]; //同上,自己实现一个记录下这些信息的方法,作者是实现了一个写文本文件的方法
}
void InstallSignalHandler(void) //注册抓取函数和抓取的Signal类型,在APPDelegate中didFinishLaunchingWithOptions调用
{
signal(SIGHUP,SignalExceptionHandler);
signal(SIGINT,SignalExceptionHandler);
signal(SIGQUIT,SignalExceptionHandler);
signal(SIGABRT,SignalExceptionHandler);
signal(SIGILL,SignalExceptionHandler);
signal(SIGSEGV,SignalExceptionHandler);
signal(SIGFPE,SignalExceptionHandler);
signal(SIGBUS,SignalExceptionHandler);
signal(SIGPIPE,SignalExceptionHandler);
}
3.写完上面两个类,在APPDelegate中didFinishLaunchingWithOptions调用
-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
InstallSignalHandler();
InstallUncaughtExceptionHandler();
returnYES;
}
4.可以写一个demo,按钮函数包含一些崩溃的代码,然后就会发现抓取的崩溃的函数,被执行了,崩溃信息成功输出到了指定的文本文件中。
-(IBAction)buttonClick:(UIButton*)sender { //1.信号量
intlist[2]={1,2};
int*p= list;
free(p);
p[1]=5;
}
-(IBAction)buttonOCException:(UIButton*)sender{ //2.ios崩溃
NSArray*array=@[@"tom",@"xxx",@"ooo"];
[arrayobjectAtIndex:5];
}
5.得到了关键的堆栈信息,和崩溃原因
到这里,已经知道了,怎么获得到这些信息。下面继续讲一下,怎么根据这些信息,定位到是哪里崩溃的,以及其中可能遇到的一些问题。
●●●
如何读懂、解析日志
1.崩溃日志提供的信息
从手机直接捞出来的日志,很有可能长这样,一推十六进制的,看不出有效信息。那么问题来了,怎么样转换为看得懂的信息呢?
2.认识符号文件
符号文件是保存 16 进制函数地址映射信息的中转文件,符号集中存储着文件名、方法名、行号的信息.
符号文件和崩溃日志,具有一一对应的关系。
如何确定符合文件A和崩溃日志B是一一对应的?
在崩溃日志中会记录一个UUID;用一些工具(比如dwarfdump),可以查询符号文件的UUID;如果是一致的,那就说明这两个文件的一对对应的符号文件和崩溃日志,可以用这个符号文件解析这个崩溃日志。
然后,用dwarfdump、atos等工具,可以将崩溃日志,通过对应的符号文件,将十六进制数通过查符号表,转化为工程中的方法名,代码行号。
比如:
崩溃日志中有一段:
然后,用dwarfdump命令
命令:dwarfdump --uuidYour.app.dSYM
对比两个uuid一致,就对上了。
最后,用symbolicatecrash工具,解析崩溃日志
命令:
cd /Users/yourMac/Desktop/崩溃文件夹
symbolicatecrash ./*.crash ./*.app.dSYM> symbol.crash
就得到了崩溃日志。
3.解析的原理
(1)-原始的崩溃文件:
原始的崩溃文件其中一行,拿出来讲解
3 UncaughtExceptionDemo0x00dabe0 0x00d300e + 31698
序号 进程名 崩溃时的堆栈地址 运行时起始地址 + 偏移量
应用崩溃发生时的堆栈地址为0x00dabe0,该进程的运行时起始地址是0x00d300e,崩溃处距离进程起始地址的偏移量为十进制的31698(对应十六进制为0x0007bd2)。
三者对应关系:0x00dabe0 =0x00d300e+ 0x0007bd2
(崩溃时的堆栈地址= 运行时起始地址 + 偏移量)
接着,去符号表中查询
(2)-获取符号表起始地址
命令:$otool -lYour.app.dSYM/Contents/Resources/DWARF/Your
结果
其中vmaddr= 0x00004000 就是符号表中的起始地址。
符号表崩溃地址 = 符号表起始地址 + 偏移量
= 0x4000 + 0x7bd2
= 0xbbd2
得到符号表中的崩溃地址
(3)-提取.debug_info
命令:$ dwarfdump -e--debug-info YourPath/YourApp.dSYM/Contents/Resources/DWARF > info-e.txt
会生成一个txt,里面包含很多个如下的内容,文件内容举例:
可以知道ViewController::buttonOCException方法的地址范围:0x0000bb76-0x0000bc00。
(4)提取.debug_line
命令:$ dwarfdump -e--debug-line YourPath/YourApp.dSYM/Contents/Resources/DWARF > line-e.txt
会生成一个txt,里面包含很多个如下的内容,文件内容举例:
这里代表的意思是,每一行代码,对应的地址、偏移量。
(5)-结论,得到关键信息:
解析后的崩溃日志为
3UncaughtExceptionDemo-[ViewControllerbuttonOCException:] (ViewController.m:36)
崩溃所在源码文件:/Users/huangchong/iOSCrashUncaught-master/UncaughtExceptionDemo/ViewController.m
发生崩溃的方法:-[ViewController :buttonOCException]
发生崩溃的方法在源文件中的行号:32
崩溃发生的代码行,在源文件中得行号:36
——推荐阅读——
全面复盘!深度剖析直播答题产品架构的难点与坑>>
如何快速设计短信验证码>>
如何做好Android 端音视频测试>>
【iOS篇】从容面对App崩溃相关推荐
- APP逆向分析之钉钉抢红包插件的实现-iOS篇
花费了很多天的原创文章,转载请注明出处https://yohunl.com/ding-ding-qiang-hong-bao-cha-jian-iospian/ ,谢谢! 网络上关于微信红包的分析文章 ...
- iOS线上APP崩溃(Crash)分析
这两周一直在研究如何追踪线上的bug,如何快速分析出程序到底崩溃在什么地方,从底层了解Crash是如何产生的.如何传递的.以及是如何分析出来的.虽然项目组并没有对这些要求很严格,但是作为一个高级开发人 ...
- GJM:移动App入侵与逆向破解技术-iOS篇 【转载】
GJM:移动App入侵与逆向破解技术-iOS篇 [转载] 转载: URL http://dev.qq.com/topic/577e0acc896e9ebb6865f321 如果您有耐心看完这篇文章,您 ...
- 微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?
本文来自微信开发团队yanyang的技术分享. 1.引言 相信大家都遇到过一段特殊文本可以让iOS设备所有app闪退的经历.前段时间大年初一,又出现某个印度语字符引起iOS11系统奔溃,所幸iOS版微 ...
- 百度地图软件测试,使用 app-inspector 解析 i 调用百度地图定位的页面时 (iOS),会导致测试 app 崩溃...
环境信息: Mac:OSX 10.12.6 Xcode:8.3.3 设备:iphone 6s /ios 10.3.3 app-inspector:v2.0.6 (单独安装的 app-inspector ...
- iOS App 崩溃报告符号化,.ips崩溃报告文件分析
iOS App 崩溃报告符号化,.ips崩溃报告文件分析 2014-09-22, Mon | 评论 本文为翻译整理.来源: Symbolicating iPhone App Crash Reports ...
- iOS中Mach异常和signal信号介绍,以及当APP崩溃时做线程保活弹出程序异常提示框
我们经常会遇到APP闪退和崩溃的问题,那么我们应该通过什么变量去监听APP的异常呢?如何在程序崩溃时,保证程序不闪退,并给用户弹出一个提示框呢? 这是本文将要讲述的内容. 先介绍2个概念,Mach异常 ...
- iOS app崩溃率,如何解决线上闪退
//联系人:石虎 QQ: 1224614774昵称:嗡嘛呢叭咪哄 1.如何追踪app崩溃率,如何解决线上闪退 当iOS设备上的App应用闪退时,操作系统会生成一个crash日志,保存在设备上.cra ...
- iOS App崩溃日志分析
APP新版本上线之前,一般都会经过测试团队的反复测试,确认无bug后才会发布.发布那刻作为开发人员的你,估计欣喜若狂吧,自豪吧!!.发布后线上运行好长一段时间,均安然无恙,可突然有一天你们家CEO说, ...
最新文章
- “编程不规范,同事两行泪!”
- c语言求解热传导方程,二维稳态导热问题的数值解法.docx
- Python编程基础:第四十九节 鸭子类型Duck Typing
- PaddleOCR——申请显存不足【Allocate too much memory for the GPU memory pool, assigned 8000 MB】解决方案
- DCMTK:定义信号灯,互斥锁和读/写锁的类
- C# 设置Word文档中图片的大小
- mysql 多数据源访问_通过Spring Boot配置动态数据源访问多个数据库的实现代码
- ssm项目启动,加载数据库连接池时卡住
- Asp.net开发之旅--简单的引用母版页
- 读取Excel任务列表并显示在Outlook日历上
- 异构计算:PC的“动车组”
- 蓝桥杯13-20届真题答案解析(Java 大学 B 组)2013年省赛真题5_有理数类
- 通过AWS了解云计算系列——云计算的核心技术体系
- 模型汇总-14 多任务学习-Multitask Learning概述
- itunes不能读取iPhone的内容,请前往iPhone“偏好设置”的“摘要”选项卡,然后单击“恢复”
- Linux命令:grep -v grep的作用 使用场景
- 温度传感器MLX90614的STM32驱动实现
- Android 数据库技术
- 考公 | 粉笔网课笔记——数量 刘凯
- 技术人如何才能不焦虑
热门文章
- iOS开发基础-九宫格坐标(4)
- wall poj 1113
- vim补全html标签,vim括号引号html标签自动补全
- 虚拟机VMware 14安装教程
- 组态王6.55安装教程
- 光流 | 光流算法对比:Farneback、Horn-Schunck、Lucas-Kanade、Lucas-Kanade derivative of Gaussian(附Matlab与C++代码)
- Sony如何启动微型计算机,索尼笔记本怎么进入bios 索尼VAIO笔记本进入bios技巧
- bytebuf池_Netty默认的Bytebuf是堆内还是堆外?池化or非池化?
- 鸿蒙系统已经推出,华为号召力太吓人!鸿蒙系统发布短短两天,主流应用已开始适配!...
- java 百度贴吧 爬虫_JAVA爬虫入门