当将应用程序部署到设备时,程序将在几个周期后退出,并出现以下错误:
Program received signal: "EXC_BAD_ACCESS".
程序在iPhone模拟器上运行没有任何问题,只要我一次执行一个指令,它也会调试和运行。一旦我让它再次运行,我将击中EXC_BAD_ACCESS信号。
在这种特殊情况下,它恰好是加速度计代码中的一个错误。它不会在模拟器中执行,这就是它不会抛出任何错误的原因。但是,它将在部署到设备后执行。
这个问题的大多数答案都处理一般的EXC_BAD_ACCESS错误,因此我将保留这个选项,作为可怕的坏访问错误的统称。
EXC_BAD_ACCESS通常是非法内存访问的结果。你可以在下面的答案中找到更多信息。
您以前遇到过EXC_BAD_ACCESS信号吗?您是如何处理它的?
根据我的经验,这通常是由非法内存访问引起的。检查所有指针,特别是对象指针,以确保它们已初始化。确保你的主窗口。Xib文件(如果您正在使用的话)已正确设置,并具有所有必要的连接。
If none of that on-paper checking turns anything up, and it doesn't happen when single-stepping, try to locate the error with NSLog() statements: sprinkle your code with them, moving them around until you isolate the line that's causing the error. Then set a breakpoint on that line and run your program. When you hit the breakpoint, examine all the variables, and the objects in them, to see if anything doesn't look like you expect.I'd especially keep an eye out for variables whose object class is something you didn't expect. If a variable is supposed to contain a UIWindow but it has an NSNotification in it instead, the same underlying code error could be manifesting itself in a different way when the debugger isn't in operation.
从你的描述中,我怀疑最有可能的解释是你在内存管理中出现了一些错误。你说你已经在iPhone开发上工作了几个星期,但没有说你是否对Objective C有一般的经验。如果你来自其他背景,在你真正内化内存管理规则之前可能需要一段时间——除非你把它说得很重要。
记住,你从分配函数(通常是静态的alloc方法,但也有一些其他方法)或复制方法获得的任何东西,你也拥有内存,当你完成时必须释放它。
But if you get something back from just about anything else including factory methods (e.g. [NSString stringWithFormat]) then you'll have an autorelease reference, which means it could be released at some time in the future by other code - so it is vital that if you need to keep it around beyond the immediate function that you retain it. If you don't, the memory may remain allocated while you are using it, or be released but coincidentally still valid, during your emulator testing, but is more likely to be released and show up as bad access errors when running on the device.
追踪这些东西的最好方法,也是一个好主意(即使没有明显的问题)是在Instruments工具中运行应用程序,特别是带有Leaks选项。
不是一个完整的答案,但我收到的一个具体情况是,当我试图访问一个“死亡”的对象时,因为我试图使用自动释放:
netObjectDefinedInMyHeader = [[[MyNetObject alloc] init] autorelease];
因此,例如,我实际上是把这个作为一个对象传递给“通知”(注册为一个侦听器,观察者,无论你喜欢的习语),但它已经死亡一旦通知被发送,我将得到EXC_BAD_ACCESS。将其更改为[[MyNetObject alloc] init]并在适当的时候释放它解决了错误。
另一个可能发生这种情况的原因是,例如,如果你传入一个对象并试图存储它:
myObjectDefinedInHeader = aParameterObjectPassedIn;
稍后,当试图访问myObjectDefinedInHeader时,您可能会遇到麻烦。使用:
myObjectDefinedInHeader = [aParameterObjectPassedIn retain];
也许正是你所需要的。当然,这些只是我遇到的几个例子,还有其他原因,但这些可能是难以捉摸的,所以我提到了它们。好运!
EXC_BAD_ACCESS的主要原因是试图访问已释放的对象。
要了解如何排除此故障,请阅读本文档:
DebuggingAutoReleasePool
即使你不认为你在“释放自动释放的对象”,这也适用于你。
这个方法非常有效。我一直在用它,而且非常成功!!
总之,这解释了如何使用Cocoa的NSZombie调试类和命令行“malloc_history”工具来查找在代码中被访问的释放对象。
Sidenote:
运行仪器和检查泄漏将无助于排除EXC_BAD_ACCESS故障。我非常确定内存泄漏与EXC_BAD_ACCESS无关。泄漏的定义是您不再具有访问权限,因此不能调用它的对象。
更新:
我现在使用Instruments来调试泄漏。在Xcode 4.2中,选择Product->Profile,当Instruments启动时,选择“Zombies”。
我刚刚花了几个小时跟踪一个EXC_BAD_ACCESS,发现NSZombies和其他env vars似乎没有告诉我任何东西。
对我来说,这是一个愚蠢的NSLog声明与格式说明符,但没有参数传递。
NSLog(@"Some silly log message %@-%@");
固定的
NSLog(@"Some silly log message %@-%@", someObj1, someObj2);
这是一个很好的帖子。以下是我的经验:我在属性声明中搞砸了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;
如果您正在使用自定义字体,并且以编程方式实例化它们,则如果您之前没有在运行时注册字体,则会发生此错误。
为了确保是这样,Xcode控制台将打印如下内容:
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x1d8)
frame #0: 0x0000000180f969cc CoreText`CTFontGetClientObject + 12
...
or
* 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