问,ios版的错误分析工具umcrashtool是通过什么原理找到本机crash日志的符号化文件的

iOS崩溃调试的使用和技巧总结
招聘信息:
本文是投稿文章,作者:在iOS开发调试过程中以及上线之后,程序经常会出现崩溃的问题。简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的。现在网上有很多关于解析崩溃信息的博客,但是大多质量参差不齐,或者有些细节没有注意到。今天写一篇博客总结一下我对崩溃调试的使用和技巧,如果有哪些错误或遗漏,还请指点,谢谢!获取崩溃信息在iOS中获取崩溃信息的方式有很多,比较常见的是使用友盟、百度等第三方分析工具,或者自己收集崩溃信息并上传公司服务器。下面列举一些我们常用的崩溃分析方式:使用友盟、百度等第三方崩溃统计工具。自己实现应用内崩溃收集,并上传服务器。Xcode-Devices中直接查看某个设备的崩溃信息。使用苹果提供的Crash崩溃收集服务。收集崩溃信息苹果给我们提供了异常处理的类,NSException类。这个类可以创建一个异常对象,也可以通过这个类获取一个异常对象。这个类中我们最常用的还是一个获取崩溃信息的C函数,我们可以通过这个函数在程序发生异常的时候收集这个异常。//&将系统提供的获取崩溃信息函数写在这个方法中,以保证在程序开始运行就具有获取崩溃信息的功能
&&-&(BOOL)application:(UIApplication&*)application&didFinishLaunchingWithOptions:(NSDictionary&*)launchOptions&{
&&&&&//&将下面C函数的函数地址当做参数
&&&&&NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
&&&&&return&YES;
&&//&设置一个C函数,用来接收崩溃信息
&&void&UncaughtExceptionHandler(NSException&*exception){
&&&&&&//&可以通过exception对象获取一些崩溃信息,我们就是通过这些崩溃信息来进行解析的,例如下面的symbols数组就是我们的崩溃堆栈。
&&&&&&NSArray&*symbols&=&[exception&callStackSymbols];
&&&&&&NSString&*reason&=&[exception&reason];
&&&&&&NSString&*name&=&[exception&name];
&&}我们也可以通过下面方法获取崩溃统计的函数指针:&&NSUncaughtExceptionHandler&*handler&=&NSGetUncaughtExceptionHandler();dSYM 符号集进行崩溃分析,首先要弄懂一个概念,就是符号集。符号集是我们对ipa文件进行打包之后,和.app文件同级的后缀名为.dSYM的文件,这个文件必须使用Xcode进行打包才有。每一个.dSYM文件都有一个UUID,和.app文件中的UUID对应,代表着是一个应用。而.dSYM文件中每一条崩溃信息也有一个单独的UUID,用来和程序的UUID进行校对。我们如果不使用.dSYM文件获取到的崩溃信息都是不准确的。符号集中存储着文件名、方法名、行号的信息,是和可执行文件的16进制函数地址对应的,通过分析崩溃的.Crash文件可以准确知道具体的崩溃信息。我们每次Archive一个包之后,都会随之生成一个dSYM文件。每次发布一个版本,我们都需要备份这个文件,以方便以后的调试。进行崩溃信息符号化的时候,必须使用当前应用打包的电脑所生成的dSYM文件,其他电脑生成的文件可能会导致分析不准确的问题。Archive当程序崩溃的时候,我们可以获得到崩溃的错误堆栈,但是这个错误堆栈都是0x开头的16进制地址,需要我们使用Xcode自带的symbolicatecrash工具来将.Crash和.dSYM文件进行符号化,就可以得到详细崩溃的信息。崩溃分析命令行解析Crash文件通过Mac自带的命令行工具解析Crash文件需要具备三个文件symbolicatecrash,Xcode自带的崩溃分析工具,使用这个工具可以更精确的定位崩溃所在的位置,将0x开头的地址替换为响应的代码和具体行数。我们打包时产生的dSYM文件。崩溃时产生的Crash文件。我在解析崩溃信息的时候,首先在桌面上建立一个Crash文件夹,然后将.Crash、.dSYM、symbolicatecrash放在这个文件夹中,这样进入这个文件夹下,直接一行命令就解决了。symbolicatecrash我们可以在下面路径下可以找到,我用的是Xcode7,其他版本Xcode路径不一样,请自行Google。/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash然后Window->Organizer->Archives中,选中archive的版本右击,选择Show in Finder就可以获取dSYM文件了。dSYM文件将.Crash、.dSYM、symbolicatecrash三个文件都放在我们在桌面建立的Crash文件夹中。Crash文件夹开启命令行工具,进入崩溃文件夹中cd /Users/username/Desktop/崩溃文件夹使用命令解析Crash文件./symbolicatecrash ./*.crash ./*.app.dSYM > symbol.crash如果上面命令不成功,使用命令检查一下环境变量xcode-select -print-path返回结果:/Applications/Xcode.app/Contents/Developer/如果不是上面的结果,需要使用下面命令设置一下导出的环境变量,然后重复上面解析的操作。export DEVELOPER_DIR=/Applications/XCode.app/Contents/Developer解析完成后会生成一个新的.Crash文件,这个文件中就是崩溃详细信息。图中红色标注的部分就是我们代码崩溃的部分。解析完成的结果注意,以下情况不会有崩溃信息产生:内存访问错误(不是野指针错误)低内存,当程序内存使用过多会造成系统低内存的问题,系统会将程序内存回收因为某种原因触发看门狗机制通过Xcode查看设备崩溃信息除了上面的系统分析工具来进行分析,如果是我们自己直接使用手机连接崩溃或者崩溃之后连接手机,选择window-> devices -> 选择自己的手机 -> view device logs 就可以查看我们的崩溃信息了。view device logs只要手机上的应用是这台电脑安装打包的,这样的崩溃信息系统已经为我们符号化好了,我们只需要进去之后等一会就行(不要相信这里面的进度刷新,并不准确),如果还是没有符号化完毕 ,我们选择文件,然后右击选择Re-Sysbomlicate就可以。如果是使用其他电脑进行的打包,我们可以在这里面将Crash文件导出,自己通过命令行的方式进行解析。使用第三方崩溃分析工具现在有很多第三方工具都可以进行崩溃统计分析,使用比较多的是友盟崩溃统计,友盟崩溃统计被集成在友盟SDK中,具体用法直接看官方文档是最好的方法,下面列出友盟崩溃统计文档地址。在这里我并不推荐友盟这个第三方,而是推荐一个更好用的第三方—。这个第三方和友盟的最大区别就是可以直接将崩溃信息分析结合dSYM分析好,在web网页上展现出来,而且还可以统计崩溃数、崩溃设备、系统版本等。下面是我公司使用bugHD统计的一些崩溃情况bugHD在bugHD服务器已经帮我们使用dSYM将崩溃符号化完成。我们可以通过点击某条崩溃,查看详细崩溃堆栈,以及崩溃设备分布和系统分布。详细分布苹果自带崩溃统计工具苹果在Xcode中为我们集成了崩溃统计功能,在Window->Organizer->Crashes中可以看到Crashes苹果自带的崩溃统计工具并不推荐用,如果想要使用这个功能,需要用户在iPhone中进行设置设置->隐私->诊断与用量->诊断与用量数据(iOS8一下在通用中设置)选择自动发送,并与开发者共享即可第三方工具恶意覆盖崩溃收集统计函数应该只进行一次调用,如果用第三方的话也最好只用一个第三方,这样我们获取崩溃统计信息的途径也是唯一的。第三方统计工具并不是用的越多越好,使用多个崩溃收集第三方会导致NSSetUncaughtExceptionHandler()函数指针的恶意覆盖,导致有些第三方不能收到崩溃信息。现在很多第三方崩溃收集工具为了确保自己能最大可能的收集到崩溃信息,会对NSSetUncaughtExceptionHandler()函数指针的恶意覆盖。因为这个函数是将函数地址当做参数传递,所以只要重复调用就会被覆盖,这样就不能保证崩溃收集的稳定性。我们解析崩溃信息时,看到崩溃堆栈只有main.m文件中的崩溃,并且可以确定不是因为main.m文件中的bug导致的崩溃,就基本可以确定是NSSetUncaughtExceptionHandler()函数指针被恶意覆盖。被恶意覆盖的崩溃堆栈
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量17423点击量11185点击量9297点击量8518点击量8483点击量7847点击量7676点击量6129点击量5712
&2015 Chukong Technologies,Inc.
京公网安备89分析iOS Crash文件:符号化iOS Crash文件的3种方法 - 推酷
分析iOS Crash文件:符号化iOS Crash文件的3种方法
当你的应用提交到App Store或者各个渠道之后,请问你多久会拿到crash文件?你如何分析crash文件的呢?
上传crash文件
你的应用应当有模块能够在应用程序crash的时候上传crash信息。 要么通过用户反馈拿到crash文件,要么借助自己或第3方的crash上传模块拿到crash文件。
今天要分析的场景是你拿到用户的.crash文件之后,如何符合化crash文件(Symbolicating crash logs)的3种方法。帮助尽快找到crash原因。
crash文件例子
crash文件的部分内容:
Last Exception Backtrace:
0 CoreFoundation 0x30acaf46 exceptionPreprocess + 126
1 libobjc.A.dylib 0x3af0b6aa objc_exception_throw + 34
2 CoreFoundation 0x30a0152e -[__NSArrayM objectAtIndex:] + 226
3 appName 0x000f462a 0x4000 + 984618
4 appName 0x00352aee 0x4000 + 3468014
18 appName 0xx4000 + 21508
大家一眼就能看到:
2 CoreFoundation 0x30a0152e -[__NSArrayM objectAtIndex:] + 226
这一行有问题。
但是,第3行和第4行的:
3 appName 0x000f462a 0x4000 + 984618
4 appName 0x00352aee 0x4000 + 3468014
并没有指出到底是app的那个模块导致的问题,如何排查呢?
有如下3种方法
方法1 使用XCode
这种方法可能是最容易的方法了。
需要使用Xcode符号化 crash log,你需要下面所列的3个文件:
1. crash报告(.crash文件)
2. 符号文件 (.dsymb文件)
3. 应用程序文件 (appName.app文件,把IPA文件后缀改为zip,然后解压,Payload目录下的appName.app文件),
这里的appName是你的应用程序的名称
把这3个文件放到同一个目录下,打开Xcode的Window菜单下的organizer,然后点击Devices tab,然后选中左边的Device Logs。
然后把.crash文件拖到Device Logs或者选择下面的import导入.crash文件。
这样你就可以看到crash的详细log了。 如下图:&
方法2 使用命令行工具symbolicatecrash
有时候Xcode不能够很好的符号化crash文件。我们这里介绍如何通过symbolicatecrash来手动符号化crash log。
在处理之前,请依然将“.app“, “.dSYM”和 &.crash&文件放到同一个目录下。现在打开终端(Terminal)然后输入如下的命令:
&DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer&
然后输入命令:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash&appName.crash&appName.app&&&appName.log&
现在,符号化的crash log就保存在appName.log中了。
方法3 使用命令行工具atos
如果你有多个“.ipa”文件,多个&.dSYMB&文件,你并不太确定到底“dSYMB”文件对应哪个&.ipa&文件,那么,这个方法就非常适合你。
特别当你的应用发布到多个渠道的时候,你需要对不同渠道的crash文件,写一个自动化的分析脚本的时候,这个方法就极其有用。
这里先介绍一个概念:
什么是UUID
每一个可执行程序都有一个build UUID来唯一标识。Crash日志包含发生crash的这个应用(app)的 build UUID以及crash发生的时候,应用加载的所有库文件的[build UUID]。
那如何知道crash文件的UUID呢?
&appName&armv&
grep&--after-context=2&
&Binary&Images:&
可以得到类似如下的结果:
appName.crash-0x4000&-&0x9e7fff&appName&armv7&&8bdeaf1a0b233aca0ebb4165&&/
/mobile/Applications/A0F8AB29-35D1-4E6E-84E2-954DE7D21CA1/appName.crash.app/appName&
(请注意这里的0x4000,是模块的加载地址,后面用atos的时候会用到)
如何找到app的UUID
可以使用命令:
xcrun&dwarfdump&-–uuid&&AppName.app/ExecutableName&&
xcrun&dwarfdump&--uuid&appName.app/appName&
结果如下:
UUID:&8BDEAF1A-0B23-3AC1-A0EBB4165&(armv7)&appName.app/appName&
UUID:&5EA16BAC-BB52-&(armv7s)&appName.app/appName&
这个app有2个UUID,表明它是一个fat binnary。
它能利用最新硬件的特性,又能兼容老版本的设备。
对比上面crash文件和app文件的UUID,发现它们是匹配的:
8BDEAF1A-0B23-3AC1-A0EBB4165&
用atos命令来符号化某个特定模块加载地址
atos&[-o&AppName.app/AppName]&[-l&loadAddress]&[-arch&architecture]&
亲测,下面3种都可以:
xcrun&atos&-o&appName.app.dSYM/Contents/Resources/DWARF/appName&-l&0x4000&-arch&armv7&
xcrun&atos&-o&appName.app.dSYM/Contents/Resources/DWARF/appName&-arch&armv7&
xcrun&atos&-o&appName.app/appName&-arch&armv7&
(注:这3行选任意一行执行都可以达到目的,其中0x4000是模块的加载地址,从上面的章节可以找到如何得到这个地址。)
文章开头提到crash文件中有如下两行,
*&3&appName&0x000f462a&0x4000&+&984618&&
*&4&appName&**0x00352aee**&0x4000&+&3468014&&&
在执行了上面的:
xcrun&atos&-o&appName.app.dSYM/Contents/Resources/DWARF/appName&-l&0x4000&-arch&armv7&
之后,输入如下地址:
0x00352aee&
(crash文件中的第4行:4 appName **0x00352aee** 0x4000 + 3468014)
可以得到结果:
-[UIScrollView(UITouch)&touchesEnded:withEvent:]&(
&appName)&(UIScrollView+UITouch.h:26)&
这样就找到了应用种到底是哪个模块导致的crash问题。
本文分析了拿到用户的.crash文件之后,如何符合化crash文件的3种方法,分别有其适用场景,方法3适用于自动化crash文件的分析。
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
排版有问题
没有分页内容
视频无法显示
图片无法显示iOS dSYM文件结构剖析(上)
发表于 15:20|
作者李民湘
摘要:在iOS App开发过程中,开发者会利用Xcode打包生成.xcarchive的包文件,并通过Organizer工具可以管理、导出发布文件。本文作者从本文开始,详细剖析了打包之后的dSYM文件的结构。
CSDN移动将持续为您优选移动开发的精华内容,共同探讨移动开发的技术热点话题,涵盖移动应用、开发工具、移动游戏及引擎、智能硬件、物联网等方方面面。如果您想投稿、参与内容翻译工作,或寻求近匠报道,请发送邮件至tangxy#csdn.net(请把#改成@)。&
在iOS App开发过程中,我们会利用Xcode打包,生成.xcarchive的包文件,通过Xcode的Organizer工具可以管理、导出发布文件,相信iOS开发对于这些过程都相当地熟悉,这里就不再赘述。主要想说的是,打包之后的dSYM文件。
通过以下方式获取dSYM文件,首先打开Archives管理窗口,如下图:
每Archive一次,都会生成一条记录,找到当前记录所在的目录,如下图:
打开.xcarchive包文件会看到其目录结构,dSYMs中的dSYM包文件就是我们接下来要剖析的文件了。dSYM同样个包文件,打开之后,我们会找到一个二进制文件,如下图,例子中是一个叫Demo的二进制文件。
从目录名中,可以看出iOS使用的是DWARF文件结构,DWARF(可能的解释是:Debugging With Attributed RecordFormats)是一种调试文件结构标准,结构相当的复杂。关于DWARF的前世今生,从何而来,为何而来,如何发展,请参考或网上搜索。
dSYM文件的一个重要作用就在于,当我们的程序发生崩溃,通过crash log或其他方式,会看到调用栈信息。通过log信息,我们并不知道具体是在那个文件的哪个位置出了问题,这个时候这个二进制文件就非常的有用了,通过它我们可以通过工具去符号化,比如Xcode自带的atos,这样可以直接定位到某个文件的具体位置。
目前有很多的工具可以解析DWARF文件,比如,Mac OS中就有dwarfdump、otool等,但现有工具并不能满足我们所有的需求,现在我们了解下其内部结构,在日后开发中有需要,可以用来参考。
下面我们打开这个二进制文件。注意:以下“段”单位为4个字节。
打开文件后,先来看下文件头,结构定义参考&fat.h&。FAT二进制数据
第一段为magic,这里需要注意字节序,读出来之后需要看下是0xCAFEBABE还是0xBEBAFECA,需要根据这个来转后续读取的字节的字节序。
第二段为arch count,也就是该App或dSYM中包含哪些CPU架构,比如armv7、arm64等,这个例子中为2,表示包含了两种cpu架构。
后续段中包含cputype(0x0000000C)、cpusubtype(0x)、offset(0x)、size(0x000F6825)等数据,根据fat中的结构定义,依次读取,这里需要说明的是,如果只包含一种CPU架构的话,是没有这段fat头定义的,可以跳过这部分,直接读取Arch数据。
根据fat头中读取的offset数据,我们可以跳到文件对应的arch数据的位置,当然如果只有一种架构的话就不需要计算偏移量了。例子中32-bit
arch的offset为0x-bit arch的offset为0x000F6880。以下数据结构参考&mach.h&。Mach二进制数据
通过magic我们可以区分出是32-bit还是64-bit,64-bit多了4个字节的保留字段,这里同样需要注意字节序的问题,也就是判断magic,来确定是否需要转换字节序。
以下部分解析,以32-bit为例。UUID二进制数据
UUID是16个字节(128bit)的一段数据,是文件的唯一标识,前面提到的符号化时,这个UUID必须要和App二进制文件中的UUID一致,才能被正确的符号化。dwarfdump查看的UUID就是这段数据。读取这部分数据时通过Command结构读取的,也就是第一段(0x0000001B)表示接下来的数据类型,第二段(0x)数据的大小(包含Command数据)。SymTab二进制数据
符号表数据块结构,前二段依然是Command数据。后边4段分别为符号在文件中的偏移量(0x)、符号个数(0x)、字符串在文件中的偏移量(0x000010FC)、字符串大小(0x)。
接下来就是读取Segment和Section数据块了,和上面读取数据块结构一样是根据Command结构读取,下图展示的Segment数据和Section数据是分开的,实际在二进制文件中它们是连续的,也就是每一条Segment数据后面会紧跟着多条对应的Section数据,Section的数据总数是通过Segment结构中的nsects决定的。
Segment数据
从Segment数据中我们可以看到, __TEXT的vmaddr是0x,也就是程序的加载地址,当然这个是指32-bit的程序,64-bit是不同的。__DWARF中表明了DWARF数据块的信息,表示dSYM是DWARF格式的数据结构。
Section数据
以上为Section数据的一部分,从Section数据中,我们可以找到__debug_info、__debug_pubnames, __debug_line等调试信息,通过这些调试信息我们可以找到程序中符号的起始地址、变量类型等信息。如果我们要符号化的话,就可以通过解析这些数据得到我们想要的信息。
关于Segment和Section中类型的定义,请参考DWARF官网。
关于如何解析数据得到符号在文件中的位置,下篇再做分享。
到这里我们已经读取了符号文件头中的大部分数据,在文件头里还有一部分数据也是很重要的,就是符号块数据,他是我们程序里所有的方法信息。
Symbol二进制数据
通过SymTab中的数据可以得到Symbol在文件中的位置和个数,Symbol块数据中包含了符号的起始地址、字符串的偏移量等数据,这部分数据结构可以参考&nlist.h&
和 &stabl.h&。在这部分数据全部读取后,就可以读取所有的符号数据了,也就是接下来的数据。
Symbol String二进制数据
通过SymTab和Symbo中的数据可以得到每个符号字符串在文件中的偏移量和大小,每个符号数据是以0结尾的字符串。
我们通过以上两部分数据的组合就可以得到每个symbo在程序中的加载地址了。这些数据对于以后做符号工作都非常的有帮助。64-bit的数据解析与以上方法相同,不过要注意64-bit中的有些数据是有点差别的,解析时需要注意。
到此,关于dSYM文件中头部数据读取就完成了。头部数据都有相应的数据结构定义,读取时相对会比较容易些,解析数据时要注意字节序的问题,32-bit和64-bit数据结构的差异、字节长度的差异,DWARF版本的差异,每个数据块之间都是紧密联系的,一个字节的读取偏差就会造成后续数据的读取错误,正所谓差之毫厘,失之千里。作者简介:李民湘,Testin崩溃分析项目高级iOS开发工程师
第一时间掌握最新移动开发相关信息和技术,请关注mobilehub公众微信号(ID: mobilehub)。&
推荐阅读相关主题:
CSDN官方微信
扫描二维码,向CSDN吐槽
微信号:CSDNnews
相关热门文章新版错误分析
错误分析是友盟为移动开发者提供的 Crash 收集和分析的工具,能够帮助开发者监测 App 在移动设备上的运行状况,及时发现并解决错误,提升 App 的稳定性。11月,新版错误分析全面上线,功能有很大的提升,友盟新版错误分析力求为开发者提供优质完美的体验与服务!
新版错误分析的功能
1.可以按照错误类型、应用版本筛选错误。
2.可以根据不同的条件为错误添加标签,便于快速分类及查找错误。
3.安卓可以通过上传 mapping 文件来定位到 Crash 的具体位置。IOS 可以通过下载 XX.csv 文件后使用 umcrashtool 工具来定位。
4.可以自定义错误信息(Android)(提示:如不更新到新版SDK,新版错误分析的部分功能将不能使用。)
友盟错误分析常见问题
Q:为什么 Android 错误详情中出现乱码?
A : 使用自定义上传错误时,不要上传中文。
Q:错误详情包含哪些内容?
A: 错误列表中展示的错误摘要的生成规则是,将收集的 Crash 日志通过一定算法聚合后的错误的堆栈信息的第一行。错误详情页面展示的是错误详细的 stacktrace 以及首次发生时间、最近一次发生时间、总次数、发生错误的应用版本、终端信息。 未修复的错误列表展示最近 15 天(含今天)接收的错误类型;已修复、处理中、已忽略的错误列表展示最近 90 天(含今天)接收的错误类型。
Q:为什么测试时 crash 后无数据?
A:错误分析的数据发送策略为再次启动时发送,所以 crash 后 需要再次启动应用才能接收到数据。 其他可能性原因: 如果同时使用了其他错误统计,如果友盟先注册,其他错误统计后注册,会导致友盟的错误统计被覆盖而无数据。(Android) 如果统计 SDK 被写在子线程中,而用户是在主线程 crash,则不会被统计到。 如果调用了
[MobClick setCrashReportEnabled:NO]--IOS; MobclickAgent.setCatchUncaughtExceptions(false)--Android
关闭错误统计,将无法接收到数据。
Q:如何定位错误具体位置?
A: Android 可以通过上传 mapping 文件来定位到 Crash 的具体位置。 IOS 可以通过下载 XX.csv 文件后使用 umcrashtool 工具来定位。 详细使用方法参见:
Q:如何按日期筛选错误信息?
A:目前除今日接收错误,还不支持按日期筛选。
Q:为什么有些错误没有统计到?
A:可能的原因有以下几点 ①今日错误数展示的是今日收到的全部错误数(聚合后的错误类型数);当今日错误类型超过 1000 个的限制时,数据将不会继续更新。
②可能调用了这个方法:MobclickAgent.onKillProcess(Context context) 。如果开发者调用 Process.kill 或者 System.exit 之类的方法杀死进程,请务必在此之前调用此方法,用来保存统计数据。
③需要勾选接收错误信息的版本。当某版本取消选中时,该版本的错误信息将不再继续接收,但不会减少当日已接收的错误数。
更多关于友盟错误分析的使用说明问题,请到进行查看,如有产品使用问题,请直接发送至邮箱。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:22082次
积分:1144
积分:1144
排名:千里之外
原创:97篇
(1)(1)(95)iOS崩溃调试
招聘信息:
在iOS开发调试过程中以及上线之后,程序经常会出现崩溃的问题。简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的。现在网上有很多关于解析崩溃信息的博客,但是大多质量参差不齐,或者有些细节没有注意到。今天写一篇博客总结一下我对崩溃调试的使用和技巧,如果有哪些错误或遗漏,还请指点,谢谢!获取崩溃信息在iOS中获取崩溃信息的方式有很多,比较常见的是使用友盟、百度等第三方分析工具,或者自己收集崩溃信息并上传公司服务器。下面列举一些我们常用的崩溃分析方式:使用友盟、百度等第三方崩溃统计工具。自己实现应用内崩溃收集,并上传服务器。Xcode-Devices中直接查看某个设备的崩溃信息。使用苹果提供的Crash崩溃收集服务。收集崩溃信息苹果给我们提供了异常处理的类,NSException类。这个类可以创建一个异常对象,也可以通过这个类获取一个异常对象。这个类中我们最常用的还是一个获取崩溃信息的C函数,我们可以通过这个函数在程序发生异常的时候收集这个异常。//&将系统提供的获取崩溃信息函数写在这个方法中,以保证在程序开始运行就具有获取崩溃信息的功能
&&-&(BOOL)application:(UIApplication&*)application&didFinishLaunchingWithOptions:(NSDictionary&*)launchOptions&{
&&&&&//&将下面C函数的函数地址当做参数
&&&&&NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
&&&&&return&YES;
&&//&设置一个C函数,用来接收崩溃信息
&&void&UncaughtExceptionHandler(NSException&*exception){
&&&&&&//&可以通过exception对象获取一些崩溃信息,我们就是通过这些崩溃信息来进行解析的,例如下面的symbols数组就是我们的崩溃堆栈。
&&&&&&NSArray&*symbols&=&[exception&callStackSymbols];
&&&&&&NSString&*reason&=&[exception&reason];
&&&&&&NSString&*name&=&[exception&name];
&&}我们也可以通过下面方法获取崩溃统计的函数指针:NSUncaughtExceptionHandler&*handler&=&NSGetUncaughtExceptionHandler();dSYM 符号集进行崩溃分析,首先要弄懂一个概念,就是符号集。符号集是我们对ipa文件进行打包之后,和.app文件同级的后缀名为.dSYM的文件,这个文件必须使用Xcode进行打包才有。每一个.dSYM文件都有一个UUID,和.app文件中的UUID对应,代表着是一个应用。而.dSYM文件中每一条崩溃信息也有一个单独的UUID,用来和程序的UUID进行校对。我们如果不使用.dSYM文件获取到的崩溃信息都是不准确的。符号集中存储着文件名、方法名、行号的信息,是和可执行文件的16进制函数地址对应的,通过分析崩溃的.Crash文件可以准确知道具体的崩溃信息。我们每次Archive一个包之后,都会随之生成一个dSYM文件。每次发布一个版本,我们都需要备份这个文件,以方便以后的调试。进行崩溃信息符号化的时候,必须使用当前应用打包的电脑所生成的dSYM文件,其他电脑生成的文件可能会导致分析不准确的问题。Archive当程序崩溃的时候,我们可以获得到崩溃的错误堆栈,但是这个错误堆栈都是0x开头的16进制地址,需要我们使用Xcode自带的symbolicatecrash工具来将.Crash和.dSYM文件进行符号化,就可以得到详细崩溃的信息。崩溃分析命令行解析Crash文件通过Mac自带的命令行工具解析Crash文件需要具备三个文件symbolicatecrash,Xcode自带的崩溃分析工具,使用这个工具可以更精确的定位崩溃所在的位置,将0x开头的地址替换为响应的代码和具体行数。我们打包时产生的dSYM文件。崩溃时产生的Crash文件。我在解析崩溃信息的时候,首先在桌面上建立一个Crash文件夹,然后将.Crash、.dSYM、symbolicatecrash放在这个文件夹中,这样进入这个文件夹下,直接一行命令就解决了。symbolicatecrash我们可以在下面路径下可以找到,我用的是Xcode7,其他版本Xcode路径不一样,请自行Google。/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash然后Window->Organizer->Archives中,选中archive的版本右击,选择Show in Finder就可以获取dSYM文件了。dSYM文件将.Crash、.dSYM、symbolicatecrash三个文件都放在我们在桌面建立的Crash文件夹中。Crash文件夹开启命令行工具,进入崩溃文件夹中cd /Users/username/Desktop/崩溃文件夹使用命令解析Crash文件./symbolicatecrash ./*.crash ./*.app.dSYM > symbol.crash如果上面命令不成功,使用命令检查一下环境变量xcode-select -print-path返回结果:/Applications/Xcode.app/Contents/Developer/如果不是上面的结果,需要使用下面命令设置一下导出的环境变量,然后重复上面解析的操作。export DEVELOPER_DIR=/Applications/XCode.app/Contents/Developer解析完成后会生成一个新的.Crash文件,这个文件中就是崩溃详细信息。图中红色标注的部分就是我们代码崩溃的部分。解析完成的结果注意,以下情况不会有崩溃信息产生:内存访问错误(不是野指针错误)低内存,当程序内存使用过多会造成系统低内存的问题,系统会将程序内存回收因为某种原因触发看门狗机制通过Xcode查看设备崩溃信息除了上面的系统分析工具来进行分析,如果是我们自己直接使用手机连接崩溃或者崩溃之后连接手机,选择window-> devices -> 选择自己的手机 -> view device logs 就可以查看我们的崩溃信息了。view device logs只要手机上的应用是这台电脑安装打包的,这样的崩溃信息系统已经为我们符号化好了,我们只需要进去之后等一会就行(不要相信这里面的进度刷新,并不准确),如果还是没有符号化完毕 ,我们选择文件,然后右击选择Re-Sysbomlicate就可以。如果是使用其他电脑进行的打包,我们可以在这里面将Crash文件导出,自己通过命令行的方式进行解析。使用第三方崩溃分析工具现在有很多第三方工具都可以进行崩溃统计分析,使用比较多的是友盟崩溃统计,友盟崩溃统计被集成在友盟SDK中,具体用法直接看官方文档是最好的方法,下面列出友盟崩溃统计文档地址。在这里我并不推荐友盟这个第三方,而是推荐一个更好用的第三方—。这个第三方和友盟的最大区别就是可以直接将崩溃信息分析结合dSYM分析好,在web网页上展现出来,而且还可以统计崩溃数、崩溃设备、系统版本等。下面是我公司使用bugHD统计的一些崩溃情况bugHD在bugHD服务器已经帮我们使用dSYM将崩溃符号化完成。我们可以通过点击某条崩溃,查看详细崩溃堆栈,以及崩溃设备分布和系统分布。详细分布苹果自带崩溃统计工具苹果在Xcode中为我们集成了崩溃统计功能,在Window->Organizer->Crashes中可以看到Crashes苹果自带的崩溃统计工具并不推荐用,如果想要使用这个功能,需要用户在iPhone中进行设置设置->隐私->诊断与用量->诊断与用量数据(iOS8以下在通用中设置)选择自动发送,并与开发者共享即可第三方工具恶意覆盖崩溃收集统计函数应该只进行一次调用,如果用第三方的话也最好只用一个第三方,这样我们获取崩溃统计信息的途径也是唯一的。第三方统计工具并不是用的越多越好,使用多个崩溃收集第三方会导致NSSetUncaughtExceptionHandler()函数指针的恶意覆盖,导致有些第三方不能收到崩溃信息。现在很多第三方崩溃收集工具为了确保自己能最大可能的收集到崩溃信息,会对NSSetUncaughtExceptionHandler()函数指针的恶意覆盖。因为这个函数是将函数地址当做参数传递,所以只要重复调用就会被覆盖,这样就不能保证崩溃收集的稳定性。我们解析崩溃信息时,看到崩溃堆栈只有main.m文件中的崩溃,并且可以确定不是因为main.m文件中的bug导致的崩溃,就基本可以确定是NSSetUncaughtExceptionHandler()函数指针被恶意覆盖。被恶意覆盖的崩溃堆栈
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量17423点击量11185点击量9297点击量8518点击量8483点击量7847点击量7676点击量6129点击量5712
&2015 Chukong Technologies,Inc.
京公网安备89}

我要回帖

更多关于 ios crash 符号化 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信