iOS疑难崩溃问题梳理

负责iOS版本质量这段时间碰到了不少疑难崩溃,它们的统一特点就是崩溃栈信息十分十分不明确,导致解决起来异常困难。这里梳理和记录一下那些曾经令人头秃的崩溃。(不定期更新)

1、多线程操作NSMutable类型数据

1、NSMutableData appendBytes崩溃

5 Foundation    __NSMutableDataGrowBytes + 272
6 Foundation    -[NSConcreteMutableData appendBytes:length:] + 372
7 Foundation    ___49-[_NSDispatchData enumerateByteRangesUsingBlock:]_block_invoke + 44
8 libdispatch.dylib __dispatch_data_apply + 128
9 libdispatch.dylib dispatch_data_apply + 40
10 Foundation   -[_NSDispatchData enumerateByteRangesUsingBlock:] + 64
11 Foundation   -[NSConcreteMutableData appendData:]

2、使用BlocksKit子线程遍历__NSDictionaryM(NSMutableDictionary)崩溃

0 libobjc.A.dylib   objc_retain + 8
1 MojiWeather   __35-[NSDictionary(BlocksKit) bk_each:]_block_invoke (NSDictionary+BlocksKit.m:14)
2 CoreFoundation    -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 232
3 MojiWeather   -[NSDictionary(BlocksKit) bk_each:] (NSDictionary+BlocksKit.m:17)
4 MojiWeather   -[AdvSystemNetworkManager p_handleNoAdResponse:] (AdvSystemNetworkManager.m:394)
5 MojiWeather   __33-[GCDAsyncSocket closeWithError:]_block_invoke (GCDAsyncSocket.m:3143)
6 libdispatch.dylib __dispatch_call_block_and_release + 24
7 libdispatch.dylib __dispatch_client_callout + 16
8 libdispatch.dylib __dispatch_queue_serial_drain$VARIANT$mp + 528
9 libdispatch.dylib __dispatch_queue_invoke$VARIANT$mp + 340
10 libdispatch.dylib    __dispatch_root_queue_drain_deferred_wlh$VARIANT$mp + 404
11 libdispatch.dylib    __dispatch_workloop_worker_thread$VARIANT$mp + 644
12 libsystem_pthread.dylib  _pthread_wqthread + 932

此类崩溃的共同点都很明显
1、崩溃栈中出现了NSMutable为前缀的类对象。
2、崩溃栈均在子线程中调用。

触发场景:

多个线程同时操作NSMutableData、NSMutableArray时即容易出现崩溃。

解决方案:

1、在串行队列中进行操作。

//在串行队列中异步执行
dispatch_async(serialQueue, ^{
    //critical section,进行数据的增删改操作。
});

2、加锁。

//使用信号量加锁
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
//critical section,进行数据的增删改操作。
dispatch_semaphore_signal(self.semaphore);

备注:

苹果官方梳理的线程不安全的类

2、CTTelephonyNetworkInfo崩溃

0 libobjc.A.dylib   objc_msgSend + 16
1 CoreTelephony _ServerConnectionCallback(__CTServerConnection*, __CFString const*, __CFDictionary const*, void*) + 52
2 CoreTelephony invocation function for block in CTServerState::sendNotification_sync(CTEvent, __CFString const*, __CFDictionary const*) const + 32
3 libdispatch.dylib __dispatch_call_block_and_release + 24
4 libdispatch.dylib __dispatch_client_callout + 16
5 libdispatch.dylib __dispatch_queue_drain + 1216
6 libdispatch.dylib __dispatch_queue_invoke + 132
7 libdispatch.dylib __dispatch_root_queue_drain + 664
8 libdispatch.dylib __dispatch_worker_thread3 + 108
9 libsystem_pthread.dylib   _pthread_wqthread + 816

这个崩溃仅在iOS9及以下系统版本上出现。乍一看很令人费解,但是仔细看能注意到崩溃栈中出现了CoreTelephony这个库,在iOS9以下版本上的CTTelephonyNetworkInfo对象有bug,已经释放的CTTelephonyNetworkInfo对象会接受通知并崩溃。继续排查项目,发现旧版本Reachability里的CTTelephonyNetworkInfo不是类变量,会被多次初始化和释放,存在崩溃风险。

触发场景

多处调用旧版本的
[[Reachability reachabilityForLocalWiFi] isReachableViaWiFi]等方法。

解决方案

修改CTTelephonyNetworkInfo为类变量,或者使用AFN里的AFNetworkReachabilityManager作为替代。

备注

CTTelephonyNetworkInfo should not be released

3、内存泄露崩溃

0 libobjc.A.dylib   objc_object::release() + 16
1 libobjc.A.dylib   (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 844
2 libobjc.A.dylib   (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 844
3 libdispatch.dylib __dispatch_last_resort_autorelease_pool_pop + 36
4 libdispatch.dylib __dispatch_root_queue_drain + 1308
5 libdispatch.dylib __dispatch_worker_thread3 + 120
6 libsystem_pthread.dylib   _pthread_wqthread + 1176

通过调用栈AutoreleasePoolPage::pop,可以得知此时系统正在调用自动释放池的释放操作(通过objc_object::release()也可以看出是对象内存释放时出现的崩溃),因此判定是内存泄露问题。

触发场景

通过instrument分析,发现以下代码有严重的内存泄露问题:

MTLModel.m line 45: [obj validateValue:&validatedValue forKey:key error:error]

解决方案

参照链接,给MTLModel增加分类方法。

https://github.com/Mantle/Mantle/issues/818

https://github.com/Mantle/Mantle/issues/787#issuecomment-286608719

备注

内存泄露这类问题不同的项目有不同的原因,建议多使用instrument的leaks排查,并通过崩溃趋势来大致确认出现问题的业务模块。

4、后台操作UIWindow问题

0 libobjc.A.dylib   objc_retain + 16
1 UIKit ___39-[UIWindow _noteOverlayInsetsDidChange]_block_invoke + 132
2 UIKit __runAfterCACommitDeferredBlocks + 292
3 UIKit __cleanUpAfterCAFlushAndRunDeferredBlocks + 560
4 UIKit __afterCACommitHandler + 168
5 CoreFoundation    ___CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
6 CoreFoundation    ___CFRunLoopDoObservers + 372
7 CoreFoundation    ___CFRunLoopRun + 1024
8 CoreFoundation    CFRunLoopRunSpecific + 444
9 GraphicsServices  GSEventRunModal + 180
10 UIKit    -[UIApplication _run] + 684
11 UIKit    UIApplicationMain + 208
12 MojiWeather  main (main.m:16)
13 libdyld.dylib    _start + 4

仅在iOS10以下设备出现。崩溃栈完全得不到有用信息,但是在Bugly上传的页面跟踪数据中可以看出每次崩溃的页面停留都是刚启动应用时在二级Splash展示时崩溃,我们项目中的二级Splash是通过设置RootViewController的方式展示的,因此基本判断是操作Splash的Window时出现的崩溃。继续排查log,发现几乎所有崩溃用户在application:didFinishLaunchingWithOptions:方法中的launchOption的key值都是UIApplicationLaunchOptionsLocationKey,因此判断该崩溃出现在用户后台定位发生改变时,并不是用户在前台操作产生。

触发场景

后台定位功能触发时,应用操作UIWindow导致。

解决方案

在application:didFinishLaunchingWithOptions:中判断launchOption,如果是UIApplicationLaunchOptionsLocationKey方式进入应用,则不触发二级Splash展示。即不操作UIWindow。

5、后台OpenGL绘制问题

由于项目接入了cocos2d-objc,因此陆陆续续出现过各类后台绘制问题。
这里统一梳理一下:只要崩溃栈中出现GLEngine、OpenGLES、gpusSubmitDataBuffers等相关字眼,即确认为绘制问题。

触发场景

这里的场景有两种:1、同问题4,launchOption为UIApplicationLaunchOptionsLocationKey时其实应用还在后台,此时触发OpenGL绘制即崩溃。

2、用户手动进入后台之后(即调用UIApplication DidEnterBackground),绘制没有停止。

解决方案

1、触发后台定位进入引用时,程序会走willFinishLaunchingWithOptions和didFinishLaunchingWithOptions,但是不会走didBecomeActive,因此可以在didBecomeActive方法中增加标志位,没有走过didBecomeActive时,不触发cocos2D的绘制。

2、在didEnterBackground增加停止绘制的操作。

备注

OpenGL ES May Not Be Used in Background Apps

6、Testflight包崩溃问题。

测试使用Testflight包覆盖Debug包,频现崩溃,但是开发使用xcode Debug无法复现崩溃。导出设备崩溃日志发现崩溃栈信息为:

Application Specific Information:
abort() called

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0:
0   libsystem_kernel.dylib          0x000000021b8619fc __ulock_wait + 8
1   libdispatch.dylib               0x000000010c42d878 0x10c428000 + 22648
2   libdispatch.dylib               0x000000010c42d9b0 0x10c428000 + 22960
3   libdispatch.dylib               0x000000010c43bbb8 0x10c428000 + 80824
4   libdispatch.dylib               0x000000010c43b5d0 0x10c428000 + 79312
5   GPUToolsCore                    0x000000010c4bc488 0x10c4ac000 + 66696
6   GPUToolsCore                    0x000000010c4bf204 0x10c4ac000 + 78340
7   dyld                            0x0000000109235504 ImageLoaderMachO::doModInitFunctions+ 103684 (ImageLoader::LinkContext const&) + 404
8   dyld                            0x0000000109235738 ImageLoaderMachO::doInitialization+ 104248 (ImageLoader::LinkContext const&) + 36
9   dyld                            0x0000000109230768 ImageLoader::recursiveInitialization+ 83816 (ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 464
10  dyld                            0x000000010922f798 ImageLoader::processInitializers+ 79768 (ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 136
11  dyld                            0x000000010922f854 ImageLoader::runInitializers+ 79956 (ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 84
12  dyld                            0x000000010921e680 dyld::initializeMainExecutable+ 9856 () + 184
13  dyld                            0x0000000109223468 dyld::_main+ 29800 (macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 4600
14  dyld                            0x000000010921d044 _dyld_start + 68

解决方案

删掉包,重新安装TestFlight包进行测试。

备注

https://forums.xamarin.com/discussion/103272/crash-ios-11-version-on-ios-10-exc-crash-abort-called-in-ad-hoc

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,299评论 8 265
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,084评论 1 32
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_x阅读 15,967评论 3 119
  • 06年,读高二,首次接触war3,那个时候,天王sky如日中天,无人能挡,那时的四大鬼王各领风骚,比起moon也毫...
    90后不哭阅读 325评论 0 3
  • 我今年明明才只有18岁而已,可是就已经变得谨小慎微 家庭从来没让我安心过,我的父母好像总是在因为小事争吵,经常,我...
    凡各黎阅读 234评论 0 1