296

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

Program received signal: "EXC_BAD_ACCESS".

该程序在 iPhone 模拟器上运行没有任何问题,只要我一步一步执行说明,它也会调试和运行。一旦我让它再次运行,我就会击中EXC_BAD_ACCESS信号。

在这种特殊情况下,恰好是加速度计代码中的错误。它不会在模拟器中执行,这就是它没有抛出任何错误的原因。但是,它会在部署到设备后执行。

这个问题的大多数答案都是针对一般EXC_BAD_ACCESS错误的,所以我将把它作为一个全面的开放性来解决可怕的 Bad Access 错误。

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

EXC_BAD_ACCESS之前有遇到过信号吗,你是怎么处理的?

4

36 回答 36

201

根据您的描述,我怀疑最可能的解释是您的内存管理存在一些错误。您说您从事 iPhone 开发工作已经有几个星期了,但不是说您是否对 Objective C 有总体经验。如果您来自其他背景,则可能需要一段时间才能真正内化内存管理规则 - 除非您非常重视它。

请记住,您从分配函数(通常是静态分配方法,但还有一些其他方法)或复制方法中获得的任何内容,您也拥有内存,并且必须在完成后释放它。

但是,如果您从包括工厂方法(例如)在内的任何其他东西中得到一些东西,[NSString stringWithFormat]那么您将拥有一个自动释放引用,这意味着它可以在将来的某个时间由其他代码发布 - 因此,如果您需要,这一点至关重要将其保留在您保留它的直接功能之外。如果不这样做,内存可能会在您使用它时保持分配状态,或者在您的模拟器测试期间被释放但巧合地仍然有效,但更有可能在设备上运行时被释放并显示为错误的访问错误。

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

于 2008-11-29T23:17:07.427 回答
101

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

要了解如何解决此问题,请阅读此文档: DebuggingAutoReleasePool

即使您不认为自己在“释放自动释放的对象”,这也适用于您。

这种方法非常有效。我一直在使用它并取得了巨大的成功!!

总之,这解释了如何使用 Cocoa 的 NSZombie 调试类和命令行“malloc_history”工具来准确查找在您的代码中访问了哪些已发布对象。

边注:

运行仪器和检查泄漏将无助于排除 EXC_BAD_ACCESS 故障。我很确定内存泄漏与 EXC_BAD_ACCESS 无关。泄漏的定义是您不再有权访问的对象,因此您无法调用它。

更新: 我现在使用 Instruments 来调试泄漏。在 Xcode 4.2 中,选择 Product->Profile,当 Instruments 启动时,选择“Zombies”。

于 2009-07-01T07:27:49.463 回答
12

EXC_BAD_ACCESS 信号是将无效指针传递给系统调用的结果。我今天早些时候在 OS X 上用一个测试程序得到了一个 - 我将一个未初始化的变量传递给pthread_join(),这是由于早期的错字造成的。

我不熟悉 iPhone 开发,但您应该仔细检查您传递给系统调用的所有缓冲区指针。一直提高编译器的警告级别(使用 gcc,使用-Walland-Wextra选项)。在模拟器/调试器上启用尽可能多的诊断。

于 2008-11-29T04:08:40.223 回答
8

根据我的经验,这通常是由非法内存访问引起的。检查所有指针,尤其是对象指针,以确保它们已初始化。确保您的 MainWindow.xib 文件(如果您正在使用一个文件)设置正确,并具有所有必要的连接。

如果纸上检查都没有发现任何问题,并且单步执行时也没有发生,请尝试使用 NSLog() 语句定位错误:将它们撒在你的代码上,移动它们直到你隔离导致的行错误。然后在该行设置断点并运行您的程序。当您到达断点时,检查所有变量以及其中的对象,看看是否有任何不符合您预期的情况。我会特别注意其对象类是您未曾预料到的变量。如果一个变量应该包含一个 UIWindow 但它却有一个 NSNotification ,那么当调试器不运行时,相同的底层代码错误可能会以不同的方式表现出来。

于 2008-11-29T22:49:35.920 回答
7

我只花了几个小时跟踪 EXC_BAD_ACCESS 并发现 NSZombies 和其他环境变量似乎没有告诉我任何信息。

对我来说,这是一个带有格式说明符但没有传递参数的愚蠢 NSLog 语句。

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

由固定

NSLog(@"Some silly log message %@-%@", someObj1, someObj2);
于 2009-10-26T03:59:07.273 回答
7

Apple 开发者计划的任何参与者都可以观看 2010 WWDC 视频。有一个很棒的视频:“Session 311 - Advanced Memory Analysis with Instruments”展示了在仪器中使用僵尸和调试其他内存问题的一些示例。

如需登录页面的链接,请单击此处

于 2010-10-19T20:31:36.907 回答
6

不是一个完整的答案,但我收到的一个特定情况是当我尝试访问一个“死”的对象时,因为我试图使用自动释放:

netObjectDefinedInMyHeader = [[[MyNetObject alloc] init] autorelease];

例如,我实际上将它作为一个对象传递给“通知”(将其注册为侦听器、观察者,无论您喜欢什么成语),但是一旦发送通知,它就已经死了,我会得到 EXC_BAD_ACCESS。稍后根据需要将其更改为[[MyNetObject alloc] init]并释放它可以解决该错误。

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

myObjectDefinedInHeader = aParameterObjectPassedIn;

稍后在尝试访问 myObjectDefinedInHeader 时,您可能会遇到麻烦。使用:

myObjectDefinedInHeader = [aParameterObjectPassedIn retain];

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

于 2008-12-01T05:20:51.090 回答
6

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

可以在此处找到说明DebuggingTechniques

于 2009-12-07T00:44:44.943 回答
5

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

我有代码:

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

显然我忘记为字符串分配内存:

NSMutableString *string = [[NSMutableString alloc] init];
[string   appendWithFormat:@"foo"];

解决问题。

于 2009-07-23T11:07:06.840 回答
5

在 EXC_BAD_ACCESS 异常发生之前捕获它们的另一种方法是静态分析器,在 XCode 4+ 中。

使用 Product > Analyze (shift+cmd+B) 运行静态分析器。单击分析器生成的任何消息将覆盖源上的图表,显示有问题的对象的保留/释放顺序。

在此处输入图像描述

于 2012-12-26T19:15:18.873 回答
4

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

于 2010-02-17T08:15:14.983 回答
4

如何调试 EXC_BAD_ACCESS

查看上面的链接并按照它所说的去做......只是一些使用 NSZombies 的快速说明

运行应用程序并在它失败后(应该显示“中断”而不是“EXC_BAD_ACCESS”......检查控制台(运行>控制台)......现在应该有一条消息告诉它试图访问什么对象。

于 2010-09-15T19:13:09.833 回答
3

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

之前的属性: 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

于 2009-05-16T19:35:56.513 回答
3

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

于 2009-08-24T02:04:38.053 回答
3

我忘记在初始化方法中返回 self ... ;)

于 2010-02-09T11:54:40.950 回答
3

忘记从dealloc. 我在 UINavigationController 的 rootView 上获得了 exc_bad_access,但只是有时。我认为问题出在 rootView 中,因为它在 viewDidAppear{} 中途崩溃了。事实证明,只有在我使用错误的 dealloc{} 版本弹出视图后才会发生这种情况,就是这样!

"EXC_BAD_ACCESS" [切换到进程 330] 现在没有可用于编程的内存:调用 malloc 不安全

我认为这是我试图分配的问题......而不是我试图释放非分配的问题,D'oh!

于 2010-03-04T05:40:56.960 回答
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;
于 2010-05-03T00:50:31.770 回答
3

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

EXC_BAD_ACCESS 发生在方法的入口点之后,让我困惑了很长时间,因为它离数组声明很远。

也许其他人可能会从我几个小时的拉头发中受益。

于 2010-06-28T12:49:07.887 回答
3

我如何处理 EXC_BAD_ACCESS

有时我觉得当抛出 EXC_BAD_ACCESS 错误时,xcode 会在 main.m 类中显示错误,而不会提供崩溃发生位置的额外信息(有时)。

在那些时候,我们可以在 Xcode 中设置一个异常断点,以便在捕获到异常时放置一个断点,并直接告知用户该行发生了崩溃

在此处输入图像描述

于 2014-01-07T09:17:17.660 回答
2

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

于 2008-11-30T14:39:46.317 回答
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

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

于 2009-05-30T23:48:57.387 回答
2

我刚遇到这个问题。对我来说,原因是删除一个 CoreData 托管对象,然后尝试从另一个地方读取它。

于 2009-12-10T14:38:15.100 回答
2

只是添加

Lynda.com有一张很棒的 DVD,叫做

iPhone SDK 基础培训

第 6 章第 3 课是关于EXEC_BAD_ACCESS和使用 Zombies 的全部内容。

对我来说很好理解,不仅仅是错误代码,还有我如何使用 Zombies 来获取有关已发布对象的更多信息。

于 2010-04-05T11:16:18.037 回答
2

检查错误可能是什么

使用 NSZombieEnabled。

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

选择 Project > Edit Active Executable 打开可执行信息窗口。单击参数。单击“要在环境中设置的变量”部分中的添加 (+) 按钮。在 Name 列中输入 NSZombieEnabled,在 Value 列中输入 YES。确保选中 NSZombieEnabled 条目的复选标记。

我在 iPhoneSDK 上找到了这个答案

于 2011-02-23T16:52:22.710 回答
2

我意识到前段时间有人问过这个问题,但是在阅读了这个帖子之后,我找到了 XCode 4.2 的解决方案:产品 -> 编辑方案 -> 诊断选项卡 -> 启用僵尸对象

帮助我找到发送到已释放对象的消息。

于 2012-02-14T04:46:51.710 回答
2

当你有无限递归时,我认为你也可能有这个错误。这对我来说是一个案例。

于 2014-04-13T19:36:05.037 回答
1

XCode 4 及更高版本,使用 Instruments 变得非常简单。只需在 Instruments 中运行 Zombies。本教程解释得很好:debugging exc_bad_access error xcode instruments

于 2012-03-09T12:02:22.170 回答
1

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

用这个:

@"Some String"

而不是这样:

"Some String"

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

于 2012-10-18T21:09:27.630 回答
1

甚至另一种可能性:在队列中使用块时,您可能很容易尝试访问另一个队列中的对象,此时该对象已被取消分配。通常当您尝试向 GUI 发送内容时。如果您的异常断点被设置在一个奇怪的地方,那么这可能是原因。

于 2012-11-29T09:07:48.633 回答
1

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

于 2013-01-21T23:52:10.827 回答
1

在你做任何事情之前,你应该尝试:

产品 -> 清洁

并再次运行。它对我有用。否则,我会浪费时间。

于 2017-04-02T09:56:08.990 回答
0

在我的情况下,我有一个视图(A),在我有另一个视图(B)的实例。我忘记了 B 是 A 的子类。显然这会导致递归和无休止的分配。打破这个问题修复了 EXE_BAD_ACCESS 问题。

   class A: UIView {
 
      let b = B()
      .
      .
   }



   class B: A {
     .
     .
   }
于 2021-03-04T17:31:41.827 回答
0

EXC_BAD_ACCESS

EXC_BAD_ACCESS访问已经释放的对象。内核发送此异常(EXC),表示无法访问内存块(BAD ACCESS)。

  • [unowned(unsafe)]被使用
  • 当一个目标使用具有不同IPHONEOS_DEPLOYMENT_TARGET[About]的另一个目标时。在我的例子中Test,target(10.0) 使用explicit dependency[About]14.0IPHONEOS_DEPLOYMENT_TARGET
于 2021-05-10T13:22:49.650 回答
0

尝试在 12 Pro Max 上分配 140000x 屏幕高度的 ScrollView 空间时出现 EXC_BAD_ACCESS 错误。它分配得很好,直到达到大约 140,000 像素宽度。;)

于 2021-07-08T21:07:22.983 回答
0

如果您正在使用自定义字体并以编程方式对其进行实例化,则如果您之前未在运行时注册字体,则可能会发生此错误。

为了确定是否是这种情况,Xcode 控制台将打印如下内容:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x1d8)
    frame #0: 0x0000000180f969cc CoreText`CTFontGetClientObject + 12
...

或者

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x000000012341c10e CoreFoundation`CFRelease.cold.1 + 14
    frame #1: 0x00000001232ed7bd CoreFoundation`CFRelease + 77
    frame #2: 0x0000000128136990 libGSFont.dylib`GSFontGetExtraData + 112
    frame #3: 0x0000000135bc8958 UIFoundation`-[UIFont lineHeight] + 9
    frame #4: 0x00000001340149f3 UIKitCore`-[UILabel intrinsicContentSize] + 331
...

要注册自定义字体并解决该问题,您可以查看此解决方案:https ://stackoverflow.com/a/69756114/3701102

于 2021-10-28T14:56:04.850 回答
-1

在我的情况下,它是由 tableview 删除操作引起的。此解决方案解决了我的错误访问异常:https ://stackoverflow.com/a/4186786/538408

于 2015-01-12T10:57:48.043 回答