调试手机上的iPhone应用程序

时间:2010-01-29 22:50:18

标签: iphone debugging ios-simulator

我被一个我无法弄清楚如何调试的错误所困扰。基本上我在模拟器上运行我的代码,一切都很好。

但是当我转到实际设备时,我收到一个EXC_BAD_ACCESS错误。不幸的是,当在调试器下运行手机时该死的东西工作正常,所以我无法判断错误发生的位置。

我确实得到了一个我无法重现的堆栈跟踪,所以我很确定我的代码中导致问题的那一行就是这一行(但是我不能在我的生活中弄清楚如何它可能是):

[[NSNotificationCenter defaultCenter] postNotificationName:@"SubscriberChanged" object: nil];

实际错误发生在objc_msgSend大约这一行下面的四帧,但它的代码似乎是iPhone SDK的一部分,所以我没有来源检查它。

任何人都可以给我一些指示,告诉我如何找出这个问题的位置?我有一个发布这个东西的截止日期,我不能让它像这样出去......

我终于设法在调试器中重现了这一点。我得到的堆栈跟踪如下:


#0  0x30011940 in objc_msgSend ()
#1  0x3054dc80 in _nsnote_callback ()
#2  0x3024ea58 in _CFXNotificationPostNotification ()
#3  0x3054b85a in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#4  0x3054dbc0 in -[NSNotificationCenter postNotificationName:object:] ()
#5  0x000027c6 in -[My2CentsAppDelegate handleMOCChange:] (self=0x1159d0, _cmd=0x2bf90, notification=0x147400) at /Users/sdussin/Desktop/UPOD Research LLC/Development/My2Cents/Classes/My2CentsAppDelegate.m:52
#6  0x3054dc80 in _nsnote_callback ()
#7  0x3024ea58 in _CFXNotificationPostNotification ()
#8  0x3054b85a in -[NSNotificationCenter postNotificationName:object:userInfo:] ()

堆栈跟踪中的第5帧对应于上面的行。

5 个答案:

答案 0 :(得分:2)

如果您无法在调试器中重复崩溃,可以尝试其他方法来解决它:

  • 查看代码(或许请朋友或同事进行代码审查)
  • 添加logging和断言
  • 激活所有(或至少大多数)编译器警告并遵守它们
  • 确保使用[] clang 2静态分析器并遵守其警告

特别是clang非常善于发现内存管理错误。 EXC_BAD_ACCESS闻起来就像一个。

您在NSNotificationCenter注册的观察员之一可能已被释放。记住,

  

重要:通知中心   不保留观察员,   因此,你必须确保你   取消注册观察员(使用   removeObserver:或   removeObserver:name:object :)之前   他们被解除分配。 (如果你不这样做,   如果,您将生成运行时错误   中心向被释放的人发送消息   对象。)

答案 1 :(得分:2)

您可以使用NSZombieEnabled(Google it)来跟踪此类事情。除此之外,我还是第二个:你可能需要取消注册一些观察者,例如已卸载但仍注册为观察者的视图控制器。

答案 2 :(得分:1)

崩溃正在发生,因为某些对象是为您发送的通知注册的,并且在发布之前没有取消订阅。因此,当您发送通知时,它会尝试回叫该对象,然后繁荣。

查看您订阅的代码中的所有位置,并查看您错过了取消订阅的位置(例如,您是否在dealloc中取消订阅?)。

同样如我们所提到的NSZombieEnabled = YES,您可以通过右键单击XCode项目浏览器中的可执行文件来设置环境标志,然后转到Arguments选项卡并将其添加到环境变量中。然后观察日志,当你发送通知时,你会看到一条消息,上面写着“消息blah发送到解除分配的实例”。

答案 3 :(得分:1)

大头钉跟踪告诉您注册了“SubscriberChanged”通知的对象已被解除分配。处理此问题的最简单方法是查找注册“SubscriberChanged”通知的所有类,并在[dealloc]方法中取消注册。

答案 4 :(得分:-1)

通常情况下,如果遇到某些情况,某些东西在模拟器上运行而不是在设备上运行,反之亦然,原因是库/框架没有针对它崩溃的处理器进行编译。

在您的情况下,您将拥有一个可在设备上正常工作的ARM库/框架,但在i386上运行的模拟器上崩溃。我会检查为该通知注册的任何对象的继承。