在CoreGraphics / MapKit中debugging崩溃

当我的应用程序在iPhone上运行时,发生间歇性崩溃。 所有的崩溃是相同的,并以某种方式涉及MKMapView覆盖(MKCircleViews)。

从典型的iPhone 4s崩溃报告:

报告标题:

Hardware Model: iPhone4,1 Process: EL-GPS-01 [1021] Path: /var/mobile/Applications/61288E15-74B5-45B9-99A9-E0B58C767816/EL-GPS-01.app/EL-GPS-01 Identifier: EL-GPS-01 Version: ??? (???) Code Type: ARM (Native) Parent Process: launchd [1] Date/Time: 2011-11-22 15:59:41.065 +0000 OS Version: iPhone OS 5.0.1 (9A405) Report Version: 104 Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x00000000 Crashed Thread: 6 

和坠毁的线程:

 Thread 6 name: Dispatch queue: com.apple.root.default-priority Thread 6 Crashed: 0 ??? 0000000000 0 + 0 1 CoreGraphics 0x319a87c2 0x31967000 + 268226 2 CoreGraphics 0x3199a9e6 0x31967000 + 211430 3 MapKit 0x37ec3564 0x37e6f000 + 345444 4 MapKit 0x37ec3652 0x37e6f000 + 345682 5 MapKit 0x37ecc0a4 0x37e6f000 + 381092 6 QuartzCore 0x3341be18 0x33410000 + 48664 7 QuartzCore 0x334d77e0 0x33410000 + 817120 8 QuartzCore 0x3346af24 0x33410000 + 372516 9 libdispatch.dylib 0x3797e892 0x3797b000 + 14482 10 libsystem_c.dylib 0x360e31ca 0x360d9000 + 41418 11 libsystem_c.dylib 0x360e30a0 0x360d9000 + 41120 

当我的iPhone连接到我的笔记本电脑时,应用程序崩溃,我在我的输出面板中得到以下内容:

 warning: check_safe_call: could not restore current frame warning: Unable to restore previously selected frame. 

debugging器完全没有给我提供任何帮助,而且问题导航器显示堆栈上没有任何东西的崩溃线程。

有一个非常简单的项目突出了这个问题:

https://github.com/1ndivisible/MKOverlayBug

git@github.com:1ndivisible / MKOverlayBug.git

我不知道如何解决这个问题。 这里有什么资料可以使用吗? 看起来崩溃源于框架深处。

我认为你的内存不足,或者你正在运行MapKit中的一个bug。 但是在防御方面,它看起来并不像是正确使用覆盖和MK视图,并且跟踪了太多的潜在叠加,使得MKMapView过载。 例如。 当下面的方法,你正在添加50覆盖的当前位置:

 -(void)addOverlays { CLLocation *currentLocation = self.mapView.userLocation.location; for(int i = 0; i < 50; i++) { MKCircle *circle = [MKCircle circleWithCenterCoordinate:currentLocation.coordinate radius:50]; [self.mapView addOverlay:circle]; } } 

随着时间的推移,这可以添加到MKMapView需要跟踪和MKViews,它可能必须立即显示大量的覆盖。 通过您的示例代码和iPhone模拟器的位置模拟器,简单的骑车路线在MKMapView中累计超过1800 MKCircle和MKCircleViews。

这里有几件事要牢记:

  1. 不要为每个位置添加太多覆盖。 1就足够了。 50是矫枉过正。
  2. 一个MKCircle应该足够每个位置。 不知道你为什么select跟踪并在每个位置绘制如此多的圈子。
  3. 尝试更有效地将覆盖交给MapView。 只给它它所显示的地图部分所需的覆盖。 查看WWDC2011video“Session 111 – 使用MapKit在地理上可视化信息”,其中显示了如何优化这个或HazardMap示例代码。

你可以按照这些方法做一些事情:

 -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { // Add it to an NSArray that you use to keep track of ALL the overlays [self.allOverlays addObject: MKCircle *circle = [MKCircle circleWithCenterCoordinate:currentLocation.coordinate radius:50]]; // Now add it to the mapView if it is in the current region // code to check to see if currentLocation is within the current map region if (overlayIsInMapRegion){ [mapView addOverlay: circle]; } } 

然后每当区域发生变化时,计算MapView调用委托方法时所需的叠加层:

 - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated 

从mapView获取区域,并创build位于该区域的叠加数组。 有些东西是:

 - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ // Create a method that takes the region and calculates which overlays it contains NSArray *newOverlays=[self overlaysForRegion: mapView.region fromAllOverlays: self.allOverlays]; if ([newOverlays count]>0){ [mapView removeOverlays]; [mapView addOverlays: newOverlays]; } } 

希望这可以帮助。 祝你好运!

蒂姆

它是一个已知的错误。 苹果已经承认了这一点。 目前没有修复。 你所能做的只是把你的graphics复制成更less的注释。 我发现<= 3注释是安全的。

KERN_INVALID_ADDRESS在0x00000000崩溃线程:6

这告诉你一些事情试图去引用一个空指针。 您可能已经发布了一个注释,或者某些注释中的数据。 在启用僵尸的debugging器下运行应用程序,看看你得到什么。

另外,在项目上运行静态分析器,并更正find的所有问题。

到目前为止,我还没有用mapkit工作。但是我发现的最好的东西是debugging技术。 这个链接肯定会帮助你debugging你的崩溃。 在没有ARC的情况下,它几乎可以帮助我的所有项目。 您需要仔细分析debugging的输出。

http://www.cocoadev.com/index.pl?DebuggingAutorelease

希望这可以帮助你debugging崩溃….

nJoy CoDing … 🙂

我不能使用git repo来重现你的bug,也许你可以给这个场景重现错误?

在这种情况下,它可能试图在地址0处执行代码(而不是从那里访​​问数据)。如果再次使debugging器崩溃,请检查PC寄存器中的值。 如果该值为零,那么您正在执行零,不提取数据。

如果是这种情况,那么执行过程中可能会损坏堆栈。 本地variables的某些缓冲区溢出可能会将零置入栈帧的返回地址。