2013-04-10 48 views
9

今天我有一个相当有趣的exc_bad_access崩溃。大量挖掘后,我想出了以下信息(在模拟器中运行):NSLogs如何导致代码不会崩溃?

如果我刚刚运行的代码时,应用程序将随机崩溃的同时,装载数据的随机点进我的管理对象。从我所知道的情况来看,当我将数据加载到托管对象时,它总是崩溃 - 而不是从我的JSON字典转换为数据到实际使用的对象(从字符串和NSNull到ints /浮点数和nils)的部分

随机崩溃当然是邪恶的,所以我试着在调试器中逐步完成整个过程,但这并不实际 - 我正在处理大量对象,所以逐个逐个地逐个处理它们只是没有工作。所以我决定添加一些NSLog来跟踪这个过程,并尝试用这种方式来发现一个模式。

立即解决了崩溃。

只要一个NSLog,在进程中的任何地方都可以防止崩溃。

我最终追踪了堆栈跟踪并发现了实际问题:我正在线程环境中访问管理对象,但不是从关联的MOC的performBlockAndWait:方法中访问。那时,这次事故对我来说非常明显 - 我很震惊,之前我没有更多的问题。我敢打赌,有一个“小”的测试数据2-3对象的集合,并与NSLogs有没有调试代码之间,错误是非常有效的早期掩盖......但问题依然存在:

为什么NSLog防止应用程序崩溃?一个没有副作用的代码怎么会改变其他应用程序的执行?这没有道理!

+0

你使用的任何地方performSelector:方法和选择器,它不返回id类型作为参数吗?有时候NSLog可能会防止这些错误发生。在这种情况下需要使用NSInvocation – BergP 2013-04-10 19:03:50

回答

12

令人吃惊的是,这是一个相当普遍的情况:我已经看到了超过一个看似无关的地方启用日志记录一次时会立即解决了计时问题在其他地方。

这样做的原因是,NSLog,就像许多其他输出功能,具有内部同步。有一个互斥锁可以保护对NSLog的内部缓冲区的访问,无论是在NSLog本身还是在其使用的其中一个I/O库中。此同步使呼叫者能够从多个线程使用NSLog。正是这种同步改变了你的程序时间,影响了竞争条件并最终解决了崩溃。

+0

)不知道,不错,+1,只是哇 – 2013-04-10 19:05:11

+0

从来没有想过这种可能性,但我想这可能会导致我的代码如何运行的巨大变化。 Cool。 – RonLugge 2013-04-10 19:24:20

+1

@RonLugge当我们第一次发现这个发现时,我们的整个团队都被震惊了:我们得到了来自我们安装的站点的频繁随机崩溃的报告,要求他们将日志级别从“错误”转为“调试“,然后把日志发送给我们,当他们回复给我们的回复是,一旦他们调高了日志级别,他们就不能再重现崩溃了,我们一开始并不相信他们,但是一旦我们关闭了日志总是在开发中),我们自己复制了这个崩溃:) – dasblinkenlight 2013-04-10 19:32:22

3

为什么一个NSLog的阻止应用崩溃? 没有副作用的代码如何改变应用程序的其余部分的执行?这没有道理!

事实上这使得感。真。

单个NSLog强制将某些东西打印到您的控制台,这需要几秒钟的时间,并且在处理一些线程之间完成并且崩溃(可能是由于输入的不可用)。

您的错误可能是由于异步调用。你的下一个过程在完成前一个过程之前开始你的下一个过程需要来自previos过程的数据。 NSLog消耗一些时间。

+0

虽然我想到了这一点,但在这种情况下对我来说没有任何意义 - 虽然我可能处于多线程环境中,但只有一个此代码的“副本”会在任何给定的情况下运行时间(所以我有'主线程'和'数据线程)。无论是什么原因导致管理对象被解除安全不应该受到一个NSLog ...我想。 – RonLugge 2013-04-10 19:22:21

+0

我经常面对这些:( – 2013-04-10 19:24:52