美文网首页
记一次Crash分析

记一次Crash分析

作者: cnNapoleon | 来源:发表于2017-08-24 12:11 被阅读0次

    在这里主要分析使用UIWebView导致产生crash的原因。

    从我们项目的crash日志收集平台中,有诸多如下的日志:

    Application received signal 11  
    
    1   libobjc.A.dylib 0x1800bc150 _objc_msgSend + 16
    2   UIKit           0x18799156c -[UIWebView webView:resource:didFinishLoadingFromDataSource:] + 84
    3   CoreFoundation  0x18164ce80 ___invoking___ + 144
    4   CoreFoundation  0x1815422c4 -[NSInvocation invoke] + 292
    5   CoreFoundation  0x181546e9c -[NSInvocation invokeWithTarget:] + 60
    6   WebKitLegacy    0x1873d4820 <redacted>
    
    
    Application received signal 11
    
    崩溃线程
    WebThread
    格式化
    1   libobjc.A.dylib 0x1800bc150 _objc_msgSend + 16
    2   UIKit           0x187c33354 -[UIWebView webThreadWebView:resource:willSendRequest:redirectResponse:fromDataSource:] + 92
    3   WebKitLegacy    0x187477e60 <redacted>
    4   WebKitLegacy    0x1873d315c <redacted>
    5   WebCore         0x1861cdee0 WebCore::ResourceLoadNotifier::dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long, WebCore::ResourceRequest&, WebCore::ResourceResponse const&) + 232
    6   WebCore         0x186f1c494 WebCore::ResourceLoader::willSendRequestInternal(WebCore::ResourceRequest&, WebCore::ResourceResponse const&) + 556
    7   WebCore         0x18703cbb0 WebCore::SubresourceLoader::willSendRequestInternal(WebCore::ResourceRequest&, WebCore::ResourceResponse const&) + 252
    8   WebCore         0x1861cd040 WebCore::ResourceLoader::init(WebCore::ResourceRequest const&) + 288
    9   WebCore         0x1861ccdec WebCore::SubresourceLoader::startLoading() + 36
    10  WebKitLegacy    0x1874b23b0 <redacted>
    

    以前在看到这种日志的时候,就在想,signal 11崩溃日志不明确,或者说WebView的系统代码,不是我们自己的代码改不了的种种。。。

    不过现在从crash统计平台的数据看来数量相当大,是非常影响用户的体验的。所以今天就抽时间来分析分析其原因。

    从日志上看,基本都是Application received signal 11,那么signal 11是代表什么呢?

    于是翻看系统的头文件sys/signal.h, 我们可以发现里面有一个宏定义#define SIGSEGV 11 /* segmentation violation */, 这个SIGSEGV其实就是signal 11的宏定义,注释很明确了:无效的内存引用

    那么问题就来了,WebCore内部发出无效内存引用,我们好像也无能为力啊???咋办呢?

    这时候就去看看UIWebView有没有其它什么可能的原因,发现在头delegate的定义
    @property (nullable, nonatomic, assign) id <UIWebViewDelegate> delegate;
    我们都知道assign一般是用于元类型,delegate在ARC下一般是被声明为weak

    这就奇怪了,怎么这么声明呢? 因此带着疑问去看UIWebView的文档:

    Protocol
    UIWebViewDelegate
    The UIWebViewDelegate protocol defines methods that a delegate of a 
    UIWebView
     object can optionally implement to intervene when web content is loaded.
    SDK
    
    iOS 2.0+
    Framework
    
    UIKit
    On This Page
    
    Overview
    Topics
    Relationships
    See Also
    Overview
    
    > Important
    > Before releasing an instance of UIWebView for which you have set a delegate,
    > you must first set the UIWebView delegate property to nil before disposing of the UIWebView instance. 
    > This can be done, for example, in the dealloc method where you dispose of the UIWebView.`
    >
    

    意思就是: 在释放一个你已经为其设过 delegate 的 UIWebView 实例之前,你首先一定要将该 UIWebView 对象的 delegate 属性设为 nil。比如说,你可以在你的 dealloc 方法中这样做。

    这时候就恍然大悟了,我们的项目中对WebView的使用并没有如此!!! 因为在UIWebView的delgate属性为assign 在被销毁的时候delegate不会被设为nil,导致WebView回调的时候引用的delegate已经是无效的内存指针了,因为指针指向的内存已经被释放,但指针没有被置空,这也正是文档里面为什么要重要强调需要在销毁前设置为nil的原因。

    这也解释了为什么crash日志中总是收到莫名的WebView的crash,而且都是Application received signal 11(即无效的内存引用

    到这里,相信大家都应该知道什么原因了,修改 UIWebView 的 delegate 的对象的 dealloc 方法中添加 _webView.delegate = nil; 如下:

    - (void)dealloc{
        /*
         Important
         Before releasing an instance of UIWebView for which you have set a delegate,
         you must first set the UIWebView delegate property to nil before disposing of the UIWebView instance. 
         This can be done, for example, in the dealloc method where you dispose of the UIWebView.
         */
        if (self.webView.loading) {
            [self.webView stopLoading];
        }
        self.webView.delegate = nil;
    }
    

    ps:由于很少写文章,所以写出来的都是没深度没难度的流水帐。这里也就记录一下这个过程,以便以后遇到类似问题能够有不至于无从下手。如有错误,望看官们不吝指正。万分感激!

    相关文章

      网友评论

          本文标题:记一次Crash分析

          本文链接:https://www.haomeiwen.com/subject/mwasdxtx.html