在XCode上EXC_BAD_ACCESS中断?

我是一般的iPhone开发和XCode的新手,不知道如何开始排除EXC_BAD_ACCESS信号。 如何让XCode在导致错误的确切线上断开?


我似乎无法让XCode停止在导致问题的线上,但我在我的debugging控制台中看到以下行:

Sun 10月25日15:12:14 jasonsmacbook TestProject [1289]:CGContextSetStrokeColorWithColor:无效上下文

Sun 10月25日15:12:14 jasonsmacbook TestProject [1289]:CGContextSetLineWidth:无效上下文

Sun 10月25日15:12:14 jasonsmacbook TestProject [1289]:CGContextAddPath:无效的上下文

Sun 10月25日15:12:14 jasonsmacbook TestProject [1289]:CGContextDrawPath:无效的上下文

2009-10-25 15:12:14.680 LanderTest [1289:207] *** – [CFArray objectAtIndex:]:发送到释放实例0x3c4e610的消息

现在,我试图绘制到我从UIGraphicsGetCurrentContext()检索的上下文,并传递给我要绘制的对象。


进一步的试验和错误debugging,我发现一个NSMutableArray我有一个对我的课属性是一个僵尸。 我进入该类的init函数,这里是我使用的代码:

 if ((self = [super init])) { NSMutableArray *array = [NSMutableArray array]; self.terrainBlocks = array; [array release]; } return self; } 

我删除了[array release]行,它不再给我EXC_BAD_ACCESS信号,但我现在困惑,为什么这个工程。 我以为当我使用这个属性的时候,它会自动保留它,所以我应该在init释放它,这样我就不会泄漏了。 我彻底困惑这是如何工作的,所有的指南和Stackoverflow的问题,我只读了我更多关于如何在我的init方法中设置属性。 对于哪种方式是最好的,似乎没有共识。

对于任何EXC_BAD_ACCESS错误,通常您都会尝试向已发布的对象发送消息。 跟踪这些最好的方法是使用NSZombieEnabled 。

这种方法从来没有实际上释放一个对象,而是通过将其包装为一个“僵尸”,并在其内部设置一个通常会被释放的标志。 这样,如果您尝试再次访问它,它仍然知道在发生错误之前是什么,并且通过这些信息,您通常可以回溯查看问题所在。

debugging器有时会在后台线程中提供有用的信息。

非常重要的是要注意的是,你需要100%,确保这只是在你的debugging代码,而不是你的分配代码。 因为什么也没有发布,你的应用程序将泄漏,泄漏和泄漏。 为了提醒我这样做,我把这个日志放在我的appdelegate中:

 if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled")) NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!"); 

如果您需要帮助查找确切的行,请执行构build和debugging( CMD-Y )而不是构build和运行( CMD-R )。 当应用程序崩溃时,debugging器会显示出你到底是哪一行,并与NSZombieEnabled结合,你应该能够找出原因。

关于你的arrays。 该线

 NSMutableArray *array = [NSMutableArray array]; 

实际上并没有给你保留的对象,而是一个autorelease对象。 它可能会保留在下一行,但不应该在第三行释放它。 看到这个

这是基本规则:

如果您使用名称以“alloc”或“new”开头或包含“copy”(例如alloc,newObject或mutableCopy)的方法创build对象,或者向其发送保留消息,则可以取得对象的所有权。 您有责任放弃使用版本或自动释放所拥有的对象的所有权。 任何其他时间你收到一个对象,你不能释放它。

在Xcode 4中,你可以点击Scheme下拉菜单(左上angular,停止button旁边) – > Edit Scheme – > Diagnostics Tab – > Enable Zombie Objects

Xcode / gdb总是在EXC_BAD_ACCESS中断,你只需要在调用堆栈上find触发它的代码即可。

请注意,这些types的错误通常会在autoreleased对象的情况下发生,这意味着问题的最终原因将不在触发EXC_BAD_ACCESS的调用堆栈中。 这就是当NSZombieEnabled和NSAutoreleaseFreedObjectCheckEnabled变得有用。

对XCode 4中旧线程的新答案…诊断EXC_BAD_ACCESSexception的最有效方法是使用Instruments来分析您的应用程序(从XCode单击产品/configuration文件并select“僵尸”)。 这将帮助您识别发送到释放对象的消息。

从Stanford CS193P类中:如果为符号objc_exception_throw添加一个断点(手动编辑断点),可以更好地了解出错的原因 – 让debugging器自行停止,让事情变得模糊并拧上堆栈跟踪。 当你在objc_exception_throw中停下时,你可以经常回头看看究竟是什么访问/操作引起了你的问题。

另一个有用的方法是设置断点,在exception发生后直接触发:

打开断点窗口(运行 – 显示 – 断点)并添加两个名为“objc_exception_throw”和“[NSException raise]”的符号断点

来自: http : //blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/

只是想为来自networking的其他人添加,为同样的错误寻找解决scheme,但不同的错误。 在我的情况下,我得到了同样的错误,当我试图实例化键名错误的NSDictionary,我忘了在我的密钥前面添加“@”:

 NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil]; 

我希望我没有错过一个相同的答案,但是我发现有些项目可能会因为在可能与项目依赖性或框架不兼容的旧iOS版本的模拟器上运行而引发此错误。 在意识到它刚刚发生在iPhone 4S之类的-older-simulator版本之前,我一直在追逐其中的一个,应用程序甚至不应该试图支持。

本来会很高兴得到一个更详细的错误信息,但我会想象这是框架的起源责任…无论如何,这是一个相当常见的search着陆,也许这将帮助别人愚弄就像我发现自己一样。

在启用僵尸之前,我build议首先摆脱所有的警告(如果有的话)。 简单的事情,像一个非void函数没有return可能会导致此错误。 如果您没有警告,请按照其他答案的build议进行操作。