将应用程序部署到设备上时,该程序将在几个周期后退出,并出现以下错误:

只要我一次逐步执行说明,它还将调试并运行。一旦让它再次运行,我就会碰到EXC_BAD_ACCESS信号。在这种情况下,它恰好是加速度计代码中的错误。它不会在模拟器中执行,这就是为什么它不会引发任何错误的原因。但是,它将在部署到设备后立即执行。

该问题的大多数答案都涉及一般的EXC_BAD_ACCESS错误,因此,我将保留所有这些内容,以解决可怕的Bad Access错误。

EXC_BAD_ACCESS通常是由于非法内存访问而引发的。您可以在下面的答案中找到更多信息。

您之前遇到过EXC_BAD_ACCESS信号,如何处理?

#1 楼

根据您的描述,我怀疑最可能的解释是您的内存管理有一些错误。您说您已经从事iPhone开发工作了几周,但对于您是否对Objective C有所了解却不是。如果您来自其他背景,则在真正内化内存管理规则之前可能要花一些时间-除非您对此有重点,否则请记住。通常是静态alloc方法,但还有一些其他方法)或copy方法,您也拥有该内存,并且必须在完成后释放它。包括工厂方法在内的任何其他内容(例如[NSString stringWithFormat]),那么您将拥有一个自动释放引用,这意味着它可能会在将来的某个时候由其他代码释放-因此至关重要的是,如果您需要将其保留在即时函数之外您保留它。如果不这样做,则在进行模拟器测试期间,内存可能会在使用时保持分配状态,或者被释放但同时仍然有效,但是更有可能被释放并在设备上运行时显示为访问错误。

跟踪这些问题的最佳方法也是一个好主意(即使没有明显的问题),最好是在Instruments工具中运行该应用程序,尤其是使用Leaks选项。 >

评论


我有一些加速度计采样代码,这些代码对我的应用而言并不重要,在删除之后,它消除了错误的访问错误。考虑到模拟器没有加速度计,这很有意义。我确实很奇怪,在导致此错误之前,这个代码已经存在了一周,没有被触及过...

–Héctor Ramos
08年11月30日在0:31

我是Objective-C的新手,所以我的大部分问题都应该来自内存管理。在使用C ++几年后,最近三,四年来我一直在使用Java,因此我对内存管理感到生疏。感谢您的回答!

–Héctor Ramos
08年11月30日,0:32

没问题-很高兴您修复了它。内存管理并非难事之上-您只需要确保学习规则并养成良好的习惯即可。

– philsquared
08年11月30日在1:14

我遇到的问题似乎完全是因为过于激进地释放了我创建的字符串(或诸如此类)。我仍然不确定要发布什么内容和发布时间,但仍不确定100%,但Phil的回答肯定有帮助。

–pluckyglen
09年5月26日下午4:37

如果我正确地遵循了cmculloh,是的,这是正确的做法。您不拥有objectAtIndex返回的对象。

– philsquared
09年9月11日在12:17

#2 楼

EXC_BAD_ACCESS的主要原因是试图访问已释放的对象。

要查找如何解决此问题,请阅读以下文档:
DebuggingAutoReleasePool

不要以为您是“释放自动释放的对象”,这将适用于您。

此方法非常有效。我一直在使用它,并取得了巨大的成功!代码。我很确定内存泄漏与EXC_BAD_ACCESS无关。泄漏的定义是您不再有权访问的对象,因此无法调用它。

UPDATE:
我现在使用Instruments来调试Leaks。在Xcode 4.2中,选择“产品”->“配置文件”,然后在Instruments启动时选择“僵尸”。

评论


该旁注非常重要。泄漏不会导致EXC_BAD_ACCESS(它们还有其他问题)。我写这篇文章是为了消除对EXC_BAD_ACCESS的误解loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html

–卢佛朗哥
10 Jul 23 '11:57

Xcode中的僵尸工具很棒!我在3分钟而不是几小时内找到了罪魁祸首。

–阿拉姆·科恰良(Aram Kocharyan)
2012年3月2日在4:50

以上答案中的链接不可用。显示404找不到错误。

– Tejas
17年1月3日在12:00

#3 楼

EXC_BAD_ACCESS信号是将无效指针传递给系统调用的结果。我今天早些时候在OS X上得到了一个测试程序-我将一个未初始化的变量传递给pthread_join(),这是由于打字错误造成的。应该仔细检查传递给系统调用的所有缓冲区指针。完全提高编译器的警告级别(使用gcc时,请使用-Wall-Wextra选项)。在模拟器/调试器上启用尽可能多的诊断。

#4 楼

以我的经验,这通常是由非法的内存访问引起的。检查所有指针,尤其是对象指针,以确保它们已初始化。如果使用的是MainWindow.xib文件,请确保已正确设置并具有所有必要的连接。如果单步执行不会发生,请尝试使用NSLog()语句查找错误:在代码中撒满代码,四处移动,直到找出导致错误的行。然后在该行上设置一个断点并运行程序。当您达到断点时,请检查所有变量以及其中的对象,以查看是否有什么不符合您的期望。我尤其要注意那些对象类不是您所期望的变量。如果一个变量应该包含一个UIWindow但其中包含一个NSNotification,则当调试器不运行时,相同的基础代码错误可能以不同的方式表现出来。

#5 楼

我只花了几个小时跟踪EXC_BAD_ACCESS,发现NSZombies和其他env var似乎什么都没告诉我。

NSLog(@"Some silly log message %@-%@");


固定在

NSLog(@"Some silly log message %@-%@", someObj1, someObj2);


#6 楼

苹果开发人员计划的任何参与者都可以使用2010 WWDC视频。
有一个很棒的视频:“会议311-使用仪器进行高级内存分析”,其中显示了一些在仪器中使用僵尸并调试其他内存问题的示例。 br />
有关登录页面的链接,请单击此处。

#7 楼

不是一个完整的答案,而是我收到的一个具体情况是,由于我尝试使用自动释放,试图访问“死”的对象时:

netObjectDefinedInMyHeader = [[[MyNetObject alloc] init] autorelease];
因此,例如,我实际上将其作为“通知”的对象传递(将其注册为侦听器,观察者,无论您喜欢哪种惯用法),但是一旦发送通知,它就已经死了,我将获得EXC_BAD_ACCESS。将其更改为[[MyNetObject alloc] init]并在以后适当时释放它可以解决该错误。

发生这种情况的另一个原因是,例如,如果您传入一个对象并尝试存储它:

myObjectDefinedInHeader = aParameterObjectPassedIn;
myObjectDefinedInHeader可能会引起麻烦。使用:

myObjectDefinedInHeader = [aParameterObjectPassedIn retain];


可能是您需要的。当然,这些只是我遇到的例子中的几个,还有其他原因,但是这些原因可能难以捉摸,因此我将其提及。祝你好运!

#8 楼

只是增加了可能发生这种情况的另一种情况:

我有以下代码:



NSMutableString *string;
[string   appendWithFormat:@"foo"];


解决了这个问题。

评论


这不会对我造成任何错误,因为将字符串初始化为nil并使用null对象模式对nil调用方法没有任何作用。

– Liron Yahdav
2014年11月14日在18:28

#9 楼

在异常发生之前捕获EXC_BAD_ACCESS异常的另一种方法是在XCode 4+中使用静态分析器。分析器生成的消息将在源上覆盖一个图表,该图表显示有问题的对象的保留/释放顺序。



#10 楼

我发现在objc_exception_throw上设置断点很有用。这样,当您获得EXC_BAD_ACCESS时,调试器应该会中断。

指令可以在这里找到DebuggingTechniques

#11 楼

使用“如果不分配或保留它,不要释放它”的简单规则。

评论


通过“ ...复制它...”扩展该规则,您应该可以。

–直到
2012年6月26日19:53

#12 楼

如何调试EXC_BAD_ACCESS

检查上面的链接,然后按说做...。显示“已中断”而不是“ EXC_BAD_ACCESS” ...检查控制台(运行>控制台)...现在应该有一条消息,告诉它正在尝试访问的对象。

-Ben

#13 楼

最近四个小时,我一直在调试和重构代码以解决此错误。上面的帖子使我看到了这个问题:

之前的属性:
startPoint = [[DataPoint alloc] init];
startPoint = [DataPointList objectAtIndex:0];



x = startPoint.x-10; // EXC_BAD_ACCESS

之后的属性:
startPoint = [[DataPoint alloc] init];
startPoint = [[DataPointList objectAtIndex:0]保留];

再见EXC_BAD_ACCESS

评论


我犯了类似的错误。我忘记找回导致崩溃的实例,我花了几个小时才弄清楚。你的经历让我发现了我的。谢谢!

– David.Chu.ca
2010年4月12日下午4:19

#14 楼

希望您在完成后释放“字符串”!

#15 楼

我忘了在init-Method中返回自己...;)

评论


这应该是编译时警告/错误,而不是运行时期间的EXC_BAD_ACCESS。

–stigi
2014年7月29日在9:03

#16 楼

这是一个很好的线程。这是我的经验:我搞砸了属性声明中的keep / assign关键字。我说:

@property (nonatomic, assign) IBOutlet UISegmentedControl *choicesControl;
@property (nonatomic, assign) IBOutlet UISwitch *africaSwitch;
@property (nonatomic, assign) IBOutlet UISwitch *asiaSwitch;


我应该说的地方

@property (nonatomic, retain) IBOutlet UISegmentedControl *choicesControl;
@property (nonatomic, retain) IBOutlet UISwitch *africaSwitch;
@property (nonatomic, retain) IBOutlet UISwitch *asiaSwitch;


评论


奇怪,为什么您需要保留IBOutlet?他们的管理为您自动完成。

– jv42
2011年1月13日在16:09

#17 楼

我仅在尝试执行包含大数组的C方法时在iPhone上遇到EXC_BAD_ACCESS。模拟器能够给我足够的内存来运行代码,但不能给设备运行(数组是一百万个字符,因此有点多余!)。

EXC_BAD_ACCESS刚好在方法的入口点之后发生,并且让我困惑了很长时间,因为它离数组声明不远。我几个小时的脱发。

#18 楼

忘记从dealloc中取出未分配的指针。我在UINavigationController的rootView上获得了exc_bad_access,但仅​​在某些时候。我认为问题出在rootView中,因为它在其viewDidAppear {}中途崩溃了。原来只有在弹出带有不良dealloc {}版本的视图后才发生,仅此而已!打电话给malloc

我以为这是我要分配的问题...而不是我要发行非分配的问题,D'oh!

#19 楼

我如何处理EXC_BAD_ACCESS

有时,我觉得当抛出EXC_BAD_ACCESS错误时,xcode将在m​​ain.m类中显示该错误,而没有提供崩溃发生位置的额外信息(有时)。 >
在那个时候,我们可以在Xcode中设置一个异常断点,以便在捕获异常时放置一个断点,并将直接提示用户该行发生了崩溃。 br />

#20 楼

验证方法参数的NSAssert()调用非常便于跟踪并避免传递nil。

#21 楼

我只是有这个问题。对我来说,原因是删除Core Data管理的对象,然后尝试从另一个地方读取它。

#22 楼

最近四个小时,我一直在调试和重构代码以解决此错误。上面的帖子使我看到了问题:

之前的属性:

startPoint = [[DataPoint alloc] init] ;
startPoint= [DataPointList objectAtIndex: 0];
x = startPoint.x - 10; // EXC_BAD_ACCESS


之后的属性:

startPoint = [[DataPoint alloc] init] ;
startPoint = [[DataPointList objectAtIndex: 0] retain];


再见EXC_BAD_ACCESS

非常感谢您的回答。我整天都在为这个问题而苦苦挣扎。太棒了!

评论


您不是立即覆盖startPoint吗?我认为您根本不需要第一行。

– toxaq
10 Sep 24'5:36

如果您要立即用另一个变量覆盖,则绝对不需要分配和初始化变量。您只是在第一次分配中泄漏了对象。

–dreamlax
2010-10-19 20:35

#23 楼

只需添加

Lynda.com就有一张很棒的DVD,名为


iPhone SDK基础培训


和第6章,第3课都是关于EXEC_BAD_ACCESS以及如何与Zombies一起使用。 />

#24 楼

要检查可能是什么错误,请使用NSZombieEnabled。

要在应用程序中激活NSZombieEnabled工具:

选择“项目”>“将活动可执行文件编辑为”打开可执行文件的“信息”窗口。
单击“参数”。
在“要在环境中设置的变量”部分中单击添加(+)按钮。
在“名称”列中输入NSZombieEnabled,然后在“是”中输入YES。 “值”列。
确保已选中NSZombieEnabled条目的复选标记。

我在iPhoneSDK上找到了此答案

#25 楼

我意识到这是在一段时间前被问到的,但是在阅读了此线程之后,我找到了XCode 4.2的解决方案:
产品->编辑方案->诊断选项卡->启用僵尸对象

已帮助我发现一条消息正在发送到已释放的对象。

#26 楼

当您进行无限递归时,我认为您也可能会遇到此错误。对我来说就是这样。

#27 楼

还有另一种可能性:在队列中使用块,很容易发生这种情况,您尝试访问另一个队列中的对象,该对象此时已被取消分配。通常,当您尝试将某些内容发送到GUI时。
如果将异常断点设置在一个陌生的地方,则可能是原因。

#28 楼

我明白了,因为我没有使用[self performSegueWithIdentifier:sender:]-(void) prepareForSegue:(UIstoryboardSegue *)

#29 楼

创建字符串时不要忘记@符号,将C-strings视为NSStrings会导致EXC_BAD_ACCESS

使用此: :

@"Some String"


PS-通常在用大量记录填充array的内容时。

#30 楼

XCode 4及更高版本,使用Instruments使其变得非常简单。只需在Instruments中运行“僵尸”即可。本教程对此进行了很好的解释:调试exc_bad_access错误xcode工具