【问题标题】:Debuggin iPhone app on the phone在手机上调试 iPhone 应用程序
【发布时间】:2011-01-11 01:37:35
【问题描述】:

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

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

【问题讨论】:

    标签: iphone debugging ios-simulator


    【解决方案1】:

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

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

    尤其是 clang 非常擅长发现内存管理错误。 EXC_BAD_ACCESS 闻起来像一个。

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

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

    【讨论】:

    • 原来通知是问题所在。我显然在我的NIB 中有几个视图对象实例。当他们被加载时,他们每个人都注册了通知,然后只有其中一个被保留了。其他人已获释,但未能取消注册通知。谢谢大家...
    【解决方案2】:

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

    【讨论】:

    • 非常好的建议 - 确保将 if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled")) NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");如果您在不需要时忘记将其关闭,则在 AppDelegate.m 中向您发出警告。
    • 我对此有一个疑问:如果我在手机上运行而不使用调试器,我如何查看 NSZombieEnabled 的输出?在调试器下运行时,我的印象是僵尸被记录到控制台,但是它们在手机上去哪里了?
    • 我的理解是(但我没有做过)当访问僵尸时会抛出一种特殊类型的异常,让您定位问题的根源。
    【解决方案3】:

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

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

    还提到了我们 NSZombieEnabled=YES,您可以通过在 XCode 项目浏览器中右键单击可执行文件,然后转到“参数”选项卡并将其添加到环境变量中来设置环境标志。然后查看日志,当您发送通知时,您会看到一条消息,内容类似于“message blah sent to deallocated instance”。

    【讨论】:

      【解决方案4】:

      跟踪跟踪告诉您,为“SubscriberChanged”通知注册的对象已被释放。处理此问题的最简单方法是查找所有注册“SubscriberChanged”通知的类,并在其 [dealloc] 方法中取消注册。

      【讨论】:

        【解决方案5】:

        通常,当您遇到在模拟器上运行但不在设备上运行或反之亦然的情况时,原因是库/框架未针对其崩溃的处理器进行编译。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-11
          • 2011-02-18
          • 1970-01-01
          • 1970-01-01
          • 2016-06-26
          相关资源
          最近更新 更多