iOS开发高手课
戴铭
前滴滴出行技术专家
立即订阅
11464 人已学习
课程目录
已完结 46 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 锚定一个点,然后在这个点上深耕
免费
基础篇 (20讲)
01 | 建立你自己的iOS开发知识体系
02 | App 启动速度怎么做优化与监控?
03 | Auto Layout 是怎么进行自动布局的,性能如何?
04 | 项目大了人员多了,架构怎么设计更合理?
05 | 链接器:符号是怎么绑定到地址上的?
06 | App 如何通过注入动态库的方式实现极速编译调试?
07 | Clang、Infer 和 OCLint ,我们应该使用谁来做静态分析?
08 | 如何利用 Clang 为 App 提质?
09 | 无侵入的埋点方案如何实现?
10 | 包大小:如何从资源和代码层面实现全方位瘦身?
11 | 热点问题答疑(一):基础模块问题答疑
12 | iOS 崩溃千奇百怪,如何全面监控?
13 | 如何利用 RunLoop 原理去监控卡顿?
14 | 临近 OOM,如何获取详细内存分配信息,分析内存问题?
15 | 日志监控:怎样获取 App 中的全量日志?
16 | 性能监控:衡量 App 质量的那把尺
17 | 远超你想象的多线程的那些坑
18 | 怎么减少 App 电量消耗?
19 | 热点问题答疑(二):基础模块问题答疑
20 | iOS开发的最佳学习路径是什么?
应用开发篇 (12讲)
21 | 除了 Cocoa,iOS还可以用哪些 GUI 框架开发?
22 | 细说 iOS 响应式框架变迁,哪些思想可以为我所用?
23 | 如何构造酷炫的物理效果和过场动画效果?
24 | A/B 测试:验证决策效果的利器
25 | 怎样构建底层的发布和订阅事件总线?
26 | 如何提高 JSON 解析的性能?
27 | 如何用 Flexbox 思路开发?跟自动布局比,Flexbox 好在哪?
28 | 怎么应对各种富文本表现需求?
29 | 如何在 iOS 中进行面向测试驱动开发和面向行为驱动开发?
30 | 如何制定一套适合自己团队的 iOS 编码规范?
31 | iOS 开发学习资料和书单推荐
32 | 热点问题答疑(三)
原理篇 (6讲)
33 | iOS 系统内核 XNU:App 如何加载?
34 | iOS 黑魔法 Runtime Method Swizzling 背后的原理
35 | libffi:动态调用和定义 C 函数
36 | iOS 是怎么管理内存的?
37 | 如何编写 Clang 插件?
38 | 热点问题答疑(四)
原生与前端共舞 (5讲)
39 | 打通前端与原生的桥梁:JavaScriptCore 能干哪些事情?
40 | React Native、Flutter 等,这些跨端方案怎么选?
41 | 原生布局转到前端布局,开发思路有哪些转变?
42 | iOS原生、大前端和Flutter分别是怎么渲染的?
43 | 剖析使 App 具有动态化和热更新能力的方案
用户故事 (1讲)
用户故事 | 我是如何学习这个专栏的?
结束语 (1讲)
结束语 | 慢几步,深几度
iOS开发高手课
登录|注册

12 | iOS 崩溃千奇百怪,如何全面监控?

戴铭 2019-04-06
你好,我是戴铭。今天我要跟你说的是崩溃监控。
App 上线后,我们最怕出现的情况就是应用崩溃了。但是,我们线下测试好好的 App,为什么上线后就发生崩溃了呢?这些崩溃日志信息是怎么采集的?能够采集的全吗?采集后又要怎么分析、解决呢?
接下来,通过今天这篇文章,你就可以了解到造成崩溃的情况有哪些,以及这些崩溃的日志都是如何捕获收集到的。
App 上线后,是很脆弱的,导致其崩溃的问题,不仅包括编写代码时的各种小马虎,还包括那些被系统强杀的疑难杂症。
下面,我们就先看看几个常见的编写代码时的小马虎,是如何让应用崩溃的。
数组越界:在取数据索引时越界,App 会发生崩溃。还有一种情况,就是给数组添加了 nil 会崩溃。
多线程问题:在子线程中进行 UI 更新可能会发生崩溃。多个线程进行数据的读取操作,因为处理时机不一致,比如有一个线程在置空数据的同时另一个线程在读取这个数据,可能会出现崩溃情况。
主线程无响应:如果主线程超过系统规定的时间无响应,就会被 Watchdog 杀掉。这时,崩溃问题对应的异常编码是 0x8badf00d。关于这个异常编码,我还会在后文和你说明。
野指针:指针指向一个已删除的对象访问内存区域时,会出现野指针崩溃。野指针问题是需要我们重点关注的,因为它是导致 App 崩溃的最常见,也是最难定位的一种情况。关于野指针等内存相关问题,我会在第 14 篇文章“临近 OOM,如何获取详细内存分配信息,分析内存问题?”里和你详细说明。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《iOS开发高手课》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(40)

  • Hjay
    文中所讲的crash捕获只说了针对信号的,基本都是需要内核操作的一些才会以信号的形式给到进程,而oc自己也有定义一些并没深入到内核的一些exception,这些是通过注册exceptionhandle来进行捕获的,所以crash的收集应该是分两块,只说信号这一种是不够完整的

    作者回复: 你说的没错,现在收集 crash 的框架都是用的Mach异常+Unix信号方式这样的方式。

    2019-04-11
    1
    7
  • yehot
    使用 registerSignalHandler 和handleSignalHandler 是能够捕获到异常。
    但是,这个时候 app 已经立即要 crash 了。捕获的异常怎么才能确保能够持久化到沙盒呢?写入文件的代码是没法保证在 crash 前正常执行完的吧!
    2019-04-08
    6
  • WeZZard
    爆棧也可以引起崩潰。看了很多 iOS 面試的鏈表題答案都是單純用的自動引用計數管理後繼節點,這種做法下鏈表長到數萬後一析構就會崩,原因就是自動引用計數引起的鏈錶各節點鏈式析構所導致的爆棧。
    2019-04-06
    6
  • Null
    老师,我是做SDK,要如何从捕获的日志中区分出来哪些是我的SDK的,哪些是主端APP的,哪些是其他Framwork。目前了解的,动态库收集的日志会有库信息,静态库收集到的信息都是APP的名字。。拜求老师指导下。
    2019-05-09
    5
  • Adam
    @Mhy
    1. ‘If your app targets iOS 9.0 and later or OS X v10.11 and later, you don't need to unregister an observer in its deallocation method。’ 在9.0之前需要手动remove 观察者,如果没有移除会出现观察者崩溃情况。
    2. NSNotification 有同步、异步、聚合发送等线程问题,不同的线程处理不好就可能出现崩溃,情况比较多可以参考一些资料。
    2019-04-06
    5
  • 周小鱼
    有个小小的建议,希望戴老师以后贴出的代码片段写一下来源或者源码链接,这样方便查看的时候快速翻阅上下文。

    作者回复: 很好的建议

    2019-04-25
    4
  • Mhy
    请问关于NSNotification线程问题能大致的讲一下吗
    2019-04-06
    1
    4
  • 鼠辈
    - (void)applicationDidEnterBackground:(UIApplication *)application {
        self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^( void) {
            [self yourTask];
        }];
    }
    这个代码中的yourTask,是后台申请3分钟之后,才会调用的吧,这个时候如果没有执行完,我试了不会崩溃。求解释
    2019-05-14
    3
  • will
    老师,我这个对吗,我看了,系统刚好在快3分钟到时候执行打印线程堆栈信息
    - (void)applicationDidEnterBackground:(UIApplication *)application {
        UIApplication *app = [UIApplication sharedApplication];
        __block UIBackgroundTaskIdentifier bgTask = 0;
        
        NSLog(@">>>>>>>>");
        
        
        bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
            NSLog(@"<<<<<<");
            NSLog(@"线程堆栈信息:%@",[NSThread callStackSymbols]);
            if (bgTask != UIBackgroundTaskInvalid) {
                [app endBackgroundTask:bgTask];
                bgTask = UIBackgroundTaskInvalid;
            }
            
        }];
    }
    2019-09-09
    2
  • 一纸丶荒年
    老师 您好 , 我 想知道的是 你讲这一篇文章 没有确切的解决问题吖, 我想了解的是 怎么来解读那些 堆栈信息. 那些崩溃日志, 都看不懂的.
    2019-08-28
    2
  • 周小明
    打印到了 1000+ 超过了10 分钟都没有 kill。请问是怎么回事呢?

    ```` objc
    - (void)applicationDidEnterBackground:(UIApplication *)application {
        [application beginBackgroundTaskWithExpirationHandler:^{
            __block int i = 1;
            dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
            dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
            dispatch_source_set_event_handler(timer, ^{
                NSLog(@"%d",i);
                i++;
                if (i > 60*100 + 5) {
                    dispatch_source_cancel(timer);
                }
                
            });
            dispatch_resume(timer);
            
        }];
    }

    ````
    2019-05-21
    2
    2
  • ssala
    我们采用的fabric监控APP crash问题,但是有些crash的堆栈完全看不出头绪,千奇百怪。
    2019-04-12
    2
  • Hiuzi
    戴老师,有没有办法在一个项目了集成某个第三方sdk的两个版本?最近被admob sdk坑惨了,一个月发了4个版本都是修复bug的,我想更新下如果有闪退只能回退老版本了,回退老版本只能发版解决了,有没有不发版的方案解决这个问题呢?

    作者回复: 没法集成两个版本,符号肯定冲突

    2019-04-11
    2
  • 小敏
    老师,收集到的crash日志怎么进行符号化?
    2019-10-15
    1
  • 青冈
    戴老师,bugly针对应用进入后台被系统强杀也算是一种crash。您告诉我是后台工作超时,那这种情况的话我是应该在DidEnterBackground这种函数中做什么处理;还是在bugly中做什么配置,不捕捉把这种情况下的crash呢? app进入后台之后,bugly抓捕crash的名称是 SEGV 是 segmentation violation 的缩写,是当一个进程执行了一个无效的内存引用,或发生段错误时发送给它的信号。这种的话,我应该

    作者回复: 在DidEnterBackground里尽快完成,不要超时了。

    2019-04-12
    1
    1
  • CoderJJMa
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(repeater) userInfo:nil repeats:YES];
        return YES;
    }

    -(void)repeater{
        
        NSLog(@"%s",__func__);
        
    }

    - (void)applicationDidEnterBackground:(UIApplication *)application {
        
        NSLog(@"===== : applicationDidEnterBackground");
        NSLog(@"begin=============");

      self.bgIdentify = [application beginBackgroundTaskWithExpirationHandler:^{
            [self endBack];
        }];
    }

    -(void)endBack{
        
        NSLog(@"end=============");
        NSLog(@"callStackSymbols : %@",[NSThread callStackSymbols]);

        [[UIApplication sharedApplication] endBackgroundTask:self.bgIdentify];
        self.bgIdentify = UIBackgroundTaskInvalid;
    }
    2019-04-08
    1
  • 普通拳
    戴老师讲解很透彻。不过我有一个疑问,很多公司的iOS开发人员有限,大部分情况下没有太多人力物力去做一些很底层的事情,比如收集崩溃日志等。您之前在滴滴的时候,这些崩溃日志的收集、性能监控等等,都是自己团队开发的吗?你们整个iOS技术团队包括业务组在内,一共大概有多少人啊?希望老师能解答我的疑惑~
    2019-12-09
  • iOS小菜鸟
    漏讲了一个重要的Mach异常,不补上吗
    2019-10-21
  • 西京富贵兔
    戴老师,关于 SIGTRAP 这种问题怎么分析好呢?
    2019-07-22
  • tomcat
    进入后台之后能在非主线程打印日志吗?主线程打印日志的话可能会造成干扰。
    2019-07-01
收起评论
40
返回
顶部