2010-01-29 112 views
0

我被一个我无法弄清楚如何调试的bug所困扰。基本上我在模拟器上运行我的代码,一切都很好。手机上的Debuggin iPhone应用程序

但是,当我转到实际设备时,出现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对应于上面的行。

回答

2

如果不能重复你的崩溃在调试器,你可以尝试其他的方法来解决它:

  • 审查代码(也许问朋友或同事的代码审查)
  • 添加logging和断言
  • 激活所有(或至少大多数)的编译器警告,并服从他们
  • 请务必使用[]铛2静态分析和听从警告

尤其是clang很擅长查找内存管理错误。 EXC_BAD_ACCESS就像一个味道。

可能是您注册的观察员之一NSNotificationCenter已发布。请记住,

重要:通知中心 不保留其观察员, 因此,你必须确保你 注销观察员(使用 removeObserver:或 removeObserver:名称:对象:) 才被释放。 (如果你不这样做, 你会如果 中心将消息发送到一个释放 对象生成运行时错误。)

+0

原来的通知是问题。我显然在我的NIB中有几个视图对象的实例。当他们得到加载时,他们每个都注册通知,然后只保留其中的一个。其他人被释放,但未能取消通知。 感谢所有... – Steve 2010-02-01 20:09:51

-1

通常,当你得到一些地方在模拟器上运行,但没有设备的情况下,反之亦然,原因是没有为处理器崩溃而编译的库/框架。

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

2

你可以使用NSZombieEnabled(谷歌它)来跟踪这类事情。除此之外,我第二个问题是:您可能需要取消某个观察者的注册,例如,一个已经卸载但仍然作为观察者注册的视图控制器。

+0

非常好的建议 - 确保把 如果(GETENV( “NSZombieEnabled”)|| GETENV( “NSAutoreleaseFreedObjectCheckEnabled”)) \t \t的NSLog(@ “启用NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled!”); 在你的AppDelegate.m中警告你,如果你不需要时忘记关闭它。 – 2010-01-30 03:56:23

+0

抱歉格式化,在评论框中没有代码标签。 – 2010-01-30 03:57:39

+0

我对此有一个问题:如果我在手机上运行而不使用调试器,我该如何看到NSZombieEnabled的输出?当我在调试器下运行僵尸时,我的印象是僵尸已经登录到控制台,但他们在哪里打电话? – Steve 2010-02-02 13:25:43

1

发生崩溃的原因是某些对象已注册您要发送的通知,并且在发布之前未取消订阅。所以当你发送通知时,它会尝试回复那个对象,然后繁荣。

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

同样如上所述,NSZombieEnabled = YES,通过右键单击XCode项目浏览器中的可执行文件并转到参数选项卡并将其添加到环境变量中来设置环境标志。然后看日志,当你发送通知时,你会看到一条消息,如“发送给释放实例的消息等等”。

1

粘性轨迹告诉你注册“SubscriberChanged”通知的对象已被释放。处理这个问题最简单的方法是寻找所有注册了“SubscriberChanged”通知的类,并让它们在[dealloc]方法中注销。

相关问题