不可重现的webcore崩溃

时间:2013-11-08 12:43:43

标签: ios objective-c ipad uiwebview crash

我有一个iPad应用程序在App Store中存在了大约三个月,我收到了一些我无法弄清楚的奇怪的崩溃报告。这些不是那么频繁,自发布以来大约有15-20个实例,但仍然经常发生实际上让我感到烦恼。崩溃略有不同(请参阅下面的堆栈跟踪),但由于它们与WebCore有关,我猜它们与应用程序中UIWebView的使用有关,可能有一个共同的原因,虽然我不是100%肯定的。该应用程序的部署目标是iOS 6.0,但iPad 2,iPad 3和iPad Mini上的崩溃仅在iOS 7上出现。

应用程序中只有一个地方我正在使用webview,用于显示各种来源的新闻文章网页。我有一个视图控制器,它的视图有UIWebView。此视图控制器中有一个实例存在于整个应用程序中,每次选择新文章时,现有webview将使用新选择文章的URL重新加载。

基于围绕WebCore问题的讨论建议的解决方案之一建议在控制器的delegate方法中将webviews nil属性设置为dealloc。不幸的是,我不认为它适用于我的情况,因为视图控制器在应用程序的生命周期中没有被释放。
另一个问题可能是在CSS中出现错误图像引用的不正确网页(loadPendingImages崩溃)。虽然我找不到这样的页面 另外,我仔细检查并确保在主线程上进行与webview相关的操作。

崩溃是

Exception Type: EXC_BAD_ACCESS 
Code: KERN_INVALID_ADDRESS

使用以下堆栈跟踪(完整的here

0 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 815
1 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 788
2 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 948
3 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
4 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
5 WebCore WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 458

0 WebCore WebCore::StyleResolver::loadPendingImages() + 1153
1 WebCore WebCore::ResourceRequestBase::~ResourceRequestBase() + 104
2 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 782
3 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 948
4 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
5 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142

0 WebCore WebCore::StyleResolver::adjustRenderStyle(WebCore::RenderStyle*, WebCore::RenderStyle*, WebCore::Element*) + 19
1 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 964
2 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
3 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
4 WebCore WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 458
5 WebCore WebCore::CSSComputedStyleDeclaration::getPropertyValue(WebCore::CSSPropertyID) const + 42

0 WebCore WebCore::TimerBase::heapDeleteMin() + 37
1 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 94
2 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 94
3 WebCore WebCore::timerFired(__CFRunLoopTimer*, void*) + 24
4 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
5 CoreFoundation __CFRunLoopDoTimer + 782

有没有人遇到类似的崩溃?如果是这样的话:
1.有没有办法复制它们?
2.如何调试这些而不复制它们? 3.什么修复解决了这些问题?

谢谢!

2 个答案:

答案 0 :(得分:5)

我在一个应用程序中遇到了完全相同的问题,奇怪的是只发生在运行iOS 7的旧设备上。我怀疑这与他们无法跟上时有关。

我所拥有的是UITableView,其中一行会打开一个UIViewController,其上有UIWebView个自定义广告。我发现在较旧的设备上,对象和内存的释放比我在其他平台上看到的更频繁。通过进出屏幕2到3次,我可以很容易地在iPhone 4上模仿崩溃。作为iPhone 5,我花了15分钟做同样的事情而且不能错过它。

我知道你可能觉得你的控制器没有被dealloc'd但听起来好像它或某些引用被删除了,我也看到我的代理引用在这个应用程序中也消失了几次。

我的建议以及对我有用的是停止执行webview并尽可能将所有内容设置为nil

在我的应用程序的一个实例中,我选择在viewWillDisappear回调中执行此操作,因为在我的情况下它已经从用户处消失并稍后重新创建,因此我将所有内容都删除了:

[webView stopLoading];

self.webView.delegate = nil;
self.webView = nil;

答案 1 :(得分:1)

查看您的Javascript-to-Objective-C代码,如果您正在执行/调用javascript代码,请确保脚本不会调用对Objective-C的新调用。

这是正确的用法:

Javascript >> Objective-C

Objective-C >> Javascript

这是崩溃的原因:

Objective-C >> Javascript >> Objective-C(这可能会因某些竞争条件而崩溃)

解决方案特定于您的项目代码。但最简单的方法是将所有Javascript包装在setTimeout()中以安排在Javascript线程中执行。这是一个简单的例子,你的Objective-C代码需要执行这个脚本:

storeUserPhoneNumber("011 123 4567");

如果storeUserPhoneNumber函数在其正文中直接或间接地调用Objective-C代码,则会发生崩溃。要解决此问题,只需在setTimeout中包装代码,如下所示:

setTimeout(function() {
    storeUserPhoneNumber("011 123 4567");
}, 0);

这样做的目的是解析字符串中的Javascript代码并将其放在函数中,该函数计划在下一个事件循环时执行,并在解析JS代码后将控制权释放回Objective-C。

请记住,您需要对所有Objective-C >> Javascript来电进行此修复;)