将应用程序部署到设备时,程序将在几个周期后退出并出现以下错误:
Program received signal: "EXC_BAD_ACCESS".
该程序在iPhone模拟器上运行没有任何问题,只要我逐步执行一个指令,它也将调试和运行。只要我让它再次运行,我就会点击EXC_BAD_ACCESS
信号。
在这种特殊情况下,它恰好是加速度计代码中的错误。它不会在模拟器中执行,这就是它没有抛出任何错误的原因。但是,它将在部署到设备后执行。
这个问题的大部分答案都涉及一般的EXC_BAD_ACCESS
错误,所以我会把这个问题保留为可怕的Bad Access错误。
EXC_BAD_ACCESS
通常是由于非法内存访问而引发的。您可以在下面的答案中找到更多信息。
您之前是否遇到过EXC_BAD_ACCESS
信号,以及您是如何处理的?
答案 0 :(得分:193)
根据您的描述,我怀疑最可能的解释是您的内存管理存在一些错误。你说你已经在iPhone开发工作了几个星期,但不是你是否对Objective C有一般经验。如果你来自另一个背景,你可能需要一段时间才真正内化内存管理规则 - 除非你提出一个重点。
请记住,您从分配函数(通常是静态alloc方法,但还有其他一些方法)或复制方法获得的任何东西,您也拥有内存,并且必须在完成后释放它。
但是如果你从其他任何事情中得到回复包括工厂方法(例如[NSString stringWithFormat]
)那么你将有一个自动释放引用,这意味着它可以在某个时间发布在未来的其他代码 - 所以如果你需要保持它超出你保留它的直接功能是至关重要的。如果不这样做,内存可能会在您使用它时保持分配状态,或在模拟器测试期间被释放但巧合仍然有效,但在设备上运行时更有可能被释放并显示为错误的访问错误。
跟踪这些事情的最佳方式,无论如何都是一个好主意(即使没有明显的问题)是在“工具”工具中运行应用程序,尤其是使用“泄漏”选项。
答案 1 :(得分:99)
EXC_BAD_ACCESS的一个主要原因是尝试访问已发布的对象。
要了解如何解决此问题,请阅读以下文档: DebuggingAutoReleasePool
即使您认为自己并未“发布自动发布的对象”,这也适用于您。
此方法非常有效。我一直使用它取得了巨大的成功!!
总之,这解释了如何使用Cocoa的NSZombie调试类和命令行“malloc_history”工具来准确找到代码中已访问的已发布对象。
<强>旁注:强>
运行仪器并检查泄漏无助于排除EXC_BAD_ACCESS故障。我很确定内存泄漏与EXC_BAD_ACCESS无关。泄漏的定义是您无法再访问的对象,因此您无法调用它。
<强>更新强> 我现在使用Instruments来调试泄漏。从Xcode 4.2,选择Product-&gt; Profile,当Instruments启动时,选择“Zombies”。
答案 2 :(得分:12)
EXC_BAD_ACCESS信号是将无效指针传递给系统调用的结果。我今天早些时候在OS X上得到了一个测试程序 - 我正在将一个未初始化的变量传递给pthread_join()
,这是由于之前的拼写错误。
我不熟悉iPhone开发,但你应该仔细检查你传递给系统调用的所有缓冲区指针。一直抬起编译器的警告级别(使用gcc,使用-Wall
和-Wextra
选项)。在模拟器/调试器上启用尽可能多的诊断。
答案 3 :(得分:8)
根据我的经验,这通常是由非法内存访问引起的。检查所有指针,尤其是对象指针,以确保它们已初始化。确保您的MainWindow.xib文件(如果您使用的话)已正确设置,并具有所有必要的连接。
如果纸上检查都没有进行任何操作,并且在单步执行时不会发生这种情况,请尝试使用NSLog()语句找到错误:将代码随身携带,移动它们直到您将其隔离导致错误的行。然后在该行上设置断点并运行程序。当你点击断点时,检查所有变量及其中的对象,看看是否有任何看起来不像你期望的那样。我会特别留意那些对象类是你没想到的变量。如果一个变量应该包含一个UIWindow,但它中有一个NSNotification,那么当调试器没有运行时,相同的底层代码错误可能以不同的方式表现出来。
答案 4 :(得分:7)
我花了几个小时跟踪EXC_BAD_ACCESS并发现NSZombies和其他env vars似乎没有告诉我任何事情。
对我来说,这是一个带有格式说明符的愚蠢NSLog语句,但没有传递args。
NSLog(@"Some silly log message %@-%@");
由
修正NSLog(@"Some silly log message %@-%@", someObj1, someObj2);
答案 5 :(得分:6)
不是一个完整的答案,但我收到这个的一个特定情况是,当我尝试使用自动释放时,试图访问“死亡”的对象:
netObjectDefinedInMyHeader = [[[MyNetObject alloc] init] autorelease];
所以例如,我实际上将它作为一个对象传递给'通知'(将其注册为监听器,观察者,你喜欢的任何习惯用法)但是一旦发送通知就已经死了,我就得到了EXC_BAD_ACCESS 。将其更改为[[MyNetObject alloc] init]
并在适当的时候释放它可以解决错误。
可能发生这种情况的另一个原因是,例如,如果您传入一个对象并尝试存储它:
myObjectDefinedInHeader = aParameterObjectPassedIn;
稍后当尝试访问myObjectDefinedInHeader时,您可能会遇到麻烦。使用:
myObjectDefinedInHeader = [aParameterObjectPassedIn retain];
可能就是您所需要的。当然,这只是我遇到的几个例子,还有其他原因,但这些可能难以理解,所以我提到它们。祝你好运!
答案 6 :(得分:6)
Apple WWDC视频可供Apple开发者计划的任何参与者使用。 有一个很棒的视频:“会话311 - 使用乐器进行高级内存分析”,其中显示了在乐器中使用僵尸和调试其他内存问题的一些示例。
要获得登录页面的链接,请单击HERE。
答案 7 :(得分:5)
在XCode 4 +中,另一种捕获EXC_BAD_ACCESS异常的方法是static analyzer。
使用Product&gt;运行静态分析器分析(shift + cmd + B)。 单击分析器生成的任何消息将覆盖源上的图表,显示违规对象的保留/释放顺序。
答案 8 :(得分:5)
只是添加另一种可能发生这种情况的情况:
我有代码:
NSMutableString *string;
[string appendWithFormat:@"foo"];
显然我忘了为字符串分配内存:
NSMutableString *string = [[NSMutableString alloc] init];
[string appendWithFormat:@"foo"];
解决了这个问题。
答案 9 :(得分:5)
我发现在objc_exception_throw上设置断点很有用。这样,当您获得EXC_BAD_ACCESS时,调试器就会中断。
可以在此处找到说明DebuggingTechniques
答案 10 :(得分:4)
查看上面的链接并按原样说明....只是一些使用NSZombies的快速说明
运行应用程序并在失败后(应该显示“Interrupted”而不是“EXC_BAD_ACCESS”...检查控制台(运行&gt;控制台)......现在应该有一条消息告诉它正在尝试的对象访问。
-Ben
答案 11 :(得分:4)
使用简单的规则“如果您没有分配或保留它,请不要将其释放”。
答案 12 :(得分:3)
这是一个很好的主题。这是我的经验:我在属性声明中搞砸了retain / 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;
答案 13 :(得分:3)
我如何处理EXC_BAD_ACCESS
有时我觉得当抛出EXC_BAD_ACCESS错误时,xcode会在main.m类中显示错误,不会提供崩溃发生位置的额外信息(有时)。
在那些时候,我们可以在Xcode中设置一个异常断点,这样当捕到异常时,将放置一个断点并直接使用户知道该行发生了崩溃
答案 14 :(得分:3)
我在iPhone上遇到EXC_BAD_ACCESS,只是在尝试执行包含大数组的C方法时。模拟器能够给我足够的内存来运行代码,但不是设备(数组是一百万个字符,所以它有点过分!)。
EXC_BAD_ACCESS恰好在方法的入口点之后发生,让我困惑了很长一段时间,因为它远不及数组声明。
也许其他人可能会受益于我几个小时的拔毛。
答案 15 :(得分:3)
我忘了在init-Method中返回self ...;)
答案 16 :(得分:3)
希望你在完成后释放'字符串'!
答案 17 :(得分:3)
忘记从dealloc
取出一个非分配指针。我在UINavigationController的rootView上获取了exc_bad_access,但有时只是。我认为问题出在rootView中,因为它在viewDidAppear {}中途崩溃了。事实证明,只有在我使用坏的dealloc {}版本弹出视图后才会发生,就是这样!
“EXC_BAD_ACCESS”[切换到进程330]现在没有可用于程序的内存:调用malloc不安全
我认为这是一个问题,我试图分配...而不是我试图释放非分配,D'哦!
答案 18 :(得分:3)
我一直在调试,并重构代码以解决过去四个小时内的错误。上面的帖子让我看到了问题:
之前的财产:
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
答案 19 :(得分:2)
只是添加
Lynda.com有一张名为
的精彩DVD和第6章,第3课完全是关于 EXEC_BAD_ACCESS 并与Zombies合作。
我很高兴理解错误代码,但是如何使用Zombies获取有关已发布对象的更多信息。
答案 20 :(得分:2)
我刚遇到这个问题。对我来说,原因是删除了一个CoreData托管对象,然后尝试从另一个地方读取它。
答案 21 :(得分:2)
我一直在调试,并重构代码以解决过去四个小时内的错误。上面的帖子让我看到了问题:
之前的财产:
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
非常感谢您的回答。我整天都在努力解决这个问题。你太棒了!
答案 22 :(得分:2)
检查错误可能是什么
使用NSZombieEnabled。
在您的应用程序中激活NSZombieEnabled工具:
选择项目&gt;编辑Active Executable以打开可执行信息窗口。 单击“参数”。 单击“要在环境中设置的变量”部分中的添加(+)按钮。 在“名称”列中输入NSZombieEnabled,在“值”列中输入“是”。 确保选中NSZombieEnabled条目的复选标记。
我在iPhoneSDK上找到了这个答案
答案 23 :(得分:2)
我意识到这是前一段时间被问过的,但在阅读完这个帖子后,我找到了XCode 4.2的解决方案: 产品 - &gt;编辑方案 - &gt;诊断标签 - &gt;启用Zombie Objects
帮助我找到发送到解除分配对象的消息。
答案 24 :(得分:2)
当你有无限递归时,我认为你也可能有这个错误。这是我的理由。
答案 25 :(得分:2)
答案 26 :(得分:1)
甚至另一种可能性:在队列中使用块,您可能很容易发生尝试访问另一个队列中的对象,此时此时已经取消分配。通常当您尝试向GUI发送内容时。 如果您的异常断点设置在一个奇怪的地方,那么这可能是原因。
答案 27 :(得分:1)
在你做任何事之前,你应该尝试:
产品 - &gt;清洁强>
又跑了。它对我有用。否则,我会浪费几个小时。
答案 28 :(得分:1)
我知道了,因为我没有使用[self performSegueWithIdentifier:sender:]
和-(void) prepareForSegue:(UIstoryboardSegue *)
对
答案 29 :(得分:1)
创建字符串时不要忘记@
符号,将C-strings
视为NSStrings
会导致EXC_BAD_ACCESS
。
使用此:
@"Some String"
而不是:
"Some String"
PS - 通常在填充具有大量记录的array
的内容时。
答案 30 :(得分:1)
XCode 4及以上版本,使用乐器制作非常简单。只需在仪器中运行Zombies。本教程很好地解释了它:debugging exc_bad_access error xcode instruments
答案 31 :(得分:0)
在我的情况下,它导致了tableview删除操作。此解决方案解决了我的错误访问异常:https://stackoverflow.com/a/4186786/538408
答案 32 :(得分:0)
就我而言,我有一个视图 (A),其中我有另一个视图 (B) 的实例。我忘记了 B 是 A 的子类。显然这会导致递归和无休止的分配。打破这个问题修复了 EXE_BAD_ACCESS 问题。
class A: UIView {
let b = B()
.
.
}
class B: A {
.
.
}
答案 33 :(得分:0)
EXC_BAD_ACCESS
EXC_BAD_ACCESS
访问已释放的对象。内核发送此异常(EXC),表示无法访问内存块(BAD ACCESS)。
IPHONEOS_DEPLOYMENT_TARGET
[About] 的另一个目标时。在我的例子中,Test
target(10.0) 使用了 explicit dependency
[About] 和 14.0
IPHONEOS_DEPLOYMENT_TARGET答案 34 :(得分:0)
尝试在 12 Pro Max 上分配 140000xScreen Height 的 ScrollView 空间时出现 EXC_BAD_ACCESS 错误。它分配得很好,直到达到大约 140,000 像素宽度。 ;)