ios 收到 EXC_BAD_ACCESS 信号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/327082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:25:07  来源:igfitidea点击:

EXC_BAD_ACCESS signal received

ioscocoa-touch

提问by Héctor Ramos

When deploying the application to the device, the program will quit after a few cycles with the following error:

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

Program received signal: "EXC_BAD_ACCESS".

The program runs without any issue on the iPhone simulator, it will also debug and run as long as I step through the instructions one at a time. As soon as I let it run again, I will hit the EXC_BAD_ACCESSsignal.

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

In this particular case, it happened to be an error in the accelerometer code. It would not execute within the simulator, which is why it did not throw any errors. However, it would execute once deployed to the device.

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

Most of the answers to this question deal with the general EXC_BAD_ACCESSerror, so I will leave this open as a catch-all for the dreaded Bad Access error.

这个问题的大部分答案都涉及一般EXC_BAD_ACCESS错误,所以我将把它作为可怕的错误访问错误的全部内容。

EXC_BAD_ACCESSis typically thrown as the result of an illegal memory access. You can find more information in the answers below.

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

Have you encountered the EXC_BAD_ACCESSsignal before, and how did you deal with it?

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

采纳答案by philsquared

From your description I suspect the most likely explanation is that you have some error in your memory management. You said you've been working on iPhone development for a few weeks, but not whether you are experienced with Objective C in general. If you've come from another background it can take a little while before you really internalise the memory management rules - unless you make a big point of it.

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

Remember, anything you get from an allocation function (usually the static alloc method, but there are a few others), or a copy method, you own the memory too and must release it when you are done.

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

But if you get something back from just about anything else includingfactory 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.

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

The best way to track these things down, and a good idea anyway (even if there are no apparent problems) is to run the app in the Instruments tool, especially with the Leaks option.

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

回答by bentford

A major cause of EXC_BAD_ACCESS is from trying to access released objects.

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

To find out how to troubleshoot this, read this document: DebuggingAutoReleasePool

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

Even if you don't think you are "releasing auto-released objects", this will apply to you.

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

This method works extremely well. I use it all the time with great success!!

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

In summary, this explains how to use Cocoa's NSZombie debugging class and the command line "malloc_history" tool to find exactly what released object has been accessed in your code.

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

Sidenote:

边注:

Running Instruments and checking for leaks will not help troubleshoot EXC_BAD_ACCESS. I'm pretty sure memory leaks have nothing to do with EXC_BAD_ACCESS. The definition of a leak is an object that you no longer have access to, and you therefore cannot call it.

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

UPDATE:I now use Instruments to debug Leaks. From Xcode 4.2, choose Product->Profile and when Instruments launches, choose "Zombies".

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

回答by Adam Rosenfield

An EXC_BAD_ACCESS signal is the result of passing an invalid pointer to a system call. I got one just earlier today with a test program on OS X - I was passing an uninitialized variable to pthread_join(), which was due to an earlier typo.

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

I'm not familiar with iPhone development, but you should double-check all your buffer pointers that you're passing to system calls. Crank up your compiler's warning level all the way (with gcc, use the -Walland -Wextraoptions). Enable as many diagnostics on the simulator/debugger as possible.

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

回答by Brent Royal-Gordon

In my experience, this is generally caused by an illegal memory access. Check all pointers, especially object pointers, to make sure they're initialized. Make sure your MainWindow.xib file, if you're using one, is set up properly, with all the necessary connections.

根据我的经验,这通常是由非法内存访问引起的。检查所有指针,尤其是对象指针,以确保它们已初始化。确保您的 MainWindow.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.

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

回答by Scott Heaberlin

I just spent a couple hours tracking an EXC_BAD_ACCESS and found NSZombies and other env vars didn't seem to tell me anything.

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

For me, it was a stupid NSLog statement with format specifiers but no args passed.

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

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

Fixed by

固定由

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

回答by Rob

Not a complete answer, but one specific situation where I've received this is when trying to access an object that 'died' because I tried to use autorelease:

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

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

So for example, I was actually passing this as an object to 'notify' (registered it as a listener, observer, whatever idiom you like) but it had already died once the notification was sent and I'd get the EXC_BAD_ACCESS. Changing it to [[MyNetObject alloc] init]and releasing it later as appropriate solved the error.

例如,我实际上是将它作为一个对象传递给“通知”(将其注册为侦听器、观察者、任何你喜欢的习惯用法),但是一旦发送通知它就已经死了,我会得到 EXC_BAD_ACCESS。将其更改为[[MyNetObject alloc] init]并稍后在适当时释放它解决了错误。

Another reason this may happen is for example if you pass in an object and try to store it:

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

myObjectDefinedInHeader = aParameterObjectPassedIn;

Later when trying to access myObjectDefinedInHeader you may get into trouble. Using:

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

myObjectDefinedInHeader = [aParameterObjectPassedIn retain];

may be what you need. Of course these are just a couple of examples of what I've ran into and there are other reasons, but these can prove elusive so I mention them. Good luck!

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

回答by Jonah

The 2010 WWDC videos are available to any participants in the apple developer program. There's a great video: "Session 311 - Advanced Memory Analysis with Instruments" that shows some examples of using zombies in instruments and debugging other memory problems.

2010 年 WWDC 视频可供苹果开发者计划的任何参与者使用。有一个很棒的视频:“会话 311 - 使用仪器进行高级内存分析”,其中展示了一些在仪器中使用僵尸和调试其他内存问题的示例。

For a link to the login page click HERE.

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

回答by ericsoco

Another method for catching EXC_BAD_ACCESS exceptions before they happen is the static analyzer, in XCode 4+.

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

Run the static analyzer with Product > Analyze (shift+cmd+B). Clicking on any messages generated by the analyzer will overlay a diagram on your source showing the sequence of retains/releases of the offending object.

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

enter image description here

在此处输入图片说明

回答by gnuchu

Just to add another situation where this can happen:

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

I had the code:

我有代码:

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

Obviously I had forgotten to allocate memory for the string:

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

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

fixes the problem.

解决问题。

回答by lyonanderson

I find it useful to set a breakpoint on objc_exception_throw. That way the debugger should break when you get the EXC_BAD_ACCESS.

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

Instructions can be found here DebuggingTechniques

可以在此处找到说明DebuggingTechniques