objective-c 在 Xcode 中中断 EXC_BAD_ACCESS?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1622079/
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-09-03 22:24:28  来源:igfitidea点击:

Break on EXC_BAD_ACCESS in Xcode?

iphoneobjective-cxcodedebuggingexc-bad-access

提问by jasonh

I'm new to iPhone development and Xcode in general and have no idea how to begin troubleshooting an EXC_BAD_ACCESSsignal. How can I get Xcode to break at the exact line that is causing the error?

我一般是 iPhone 开发和 Xcode 的新手,不知道如何开始对EXC_BAD_ACCESS信号进行故障排除。如何让 Xcode 在导致错误的确切行处中断?



I can't seem to get Xcode to stop on the line causing the problem, but I do see the following lines in my debug console:

我似乎无法让 Xcode 停在导致问题的行上,但我确实在调试控制台中看到了以下几行:

Sun Oct 25 15:12:14 jasonsmacbook TestProject[1289] : CGContextSetStrokeColorWithColor: invalid context

Sun Oct 25 15:12:14 jasonsmacbook TestProject[1289] : CGContextSetLineWidth: invalid context

Sun Oct 25 15:12:14 jasonsmacbook TestProject[1289] : CGContextAddPath: invalid context

Sun Oct 25 15:12:14 jasonsmacbook TestProject[1289] : CGContextDrawPath: invalid context

2009-10-25 15:12:14.680 LanderTest[1289:207] *** -[CFArray objectAtIndex:]: message sent to deallocated instance 0x3c4e610

10 月 25 日星期日 15:12:14 jasonsmacbook TestProject [1289]:CGContextSetStrokeColorWithColor:无效上下文

10 月 25 日星期日 15:12:14 jasonsmacbook TestProject[1289]:CGContextSetLineWidth:无效上下文

10 月 25 日星期日 15:12:14 jasonsmacbook TestProject[1289]:CGContextAddPath:无效上下文

10 月 25 日星期日 15:12:14 jasonsmacbook TestProject[1289]:CGContextDrawPath:无效上下文

2009-10-25 15:12:14.680 LanderTest[1289:207] *** -[CFArray objectAtIndex:]:消息发送到释放实例 0x3c4e610

Now, I am attempting to draw to the context I retrieve from UIGraphicsGetCurrentContext()and pass to the object that I want to draw with.

现在,我试图绘制到我从中检索的上下文UIGraphicsGetCurrentContext()并传递给我想要绘制的对象。



Further trial and error debugging and I found that an NSMutableArrayI have a property for on my class was a zombie. I went into the initfunction for the class and here's the code I was using:

进一步的试错调试,我发现NSMutableArray我在我的班级上有一个属性是一个僵尸。我进入了init该类的函数,这是我使用的代码:

if ((self = [super init])) {
        NSMutableArray *array = [NSMutableArray array];
        self.terrainBlocks = array;
        [array release];
    }
    return self;    
}

I removed the [array release]line and it no longer gives me the EXC_BAD_ACCESSsignal, but I'm now confused about why this works. I thought that when I used the property, it automatically retained it for me, and thus I should release it from within initso that I don't have a leak. I'm thoroughly confused about how this works and all the guides and Stackoverflow questions I've read only confuse me more about how to set properties within my init method. There seems to be no consensus as to which way is the best.

我移除了这[array release]条线,它不再给我EXC_BAD_ACCESS信号,但我现在很困惑为什么会这样。我认为当我使用该属性时,它会自动为我保留它,因此我应该从内部释放它,init这样我就不会泄漏。我对它是如何工作的感到非常困惑,我读过的所有指南和 Stackoverflow 问题都让我更加困惑如何在我的 init 方法中设置属性。关于哪种方式最好,似乎没有达成共识。

回答by coneybeare

For any EXC_BAD_ACCESS errors, you are usually trying to send a message to a released object. The BESTway to track these down is use NSZombieEnabled.

对于任何 EXC_BAD_ACCESS 错误,您通常会尝试向已发布的对象发送消息。跟踪这些的最佳方法是使用NSZombieEnabled

This works by never actually releasing an object, but by wrapping it up as a "zombie" and setting a flag inside it that says it normally would have been released. This way, if you try to access it again, it still know what it was before you made the error, and with this little bit of information, you can usually backtrack to see what the issue was.

这是通过从不实际释放对象,而是通过将其包装为“僵尸”并在其中设置一个标志来表示它通常会被释放。这样,如果您再次尝试访问它,它仍然会在您出错之前知道它是什么,有了这些信息,您通常可以回溯以查看问题所在。

It especially helps in background threads when the Debugger sometimes craps out on any useful information.

当调试器有时会处理任何有用的信息时,它特别有助于后台线程。

VERY IMPORTANT TO NOTEhowever, is that you need to 100% make sure this is only in your debug code and not your distribution code. Because nothing is ever released, your app will leak and leak and leak. To remind me to do this, I put this log in my appdelegate:

然而,非常重要的是,您需要 100% 确保这仅在您的调试代码中,而不是您的分发代码中。因为没有任何东西被发布,你的应用程序会泄漏,泄漏和泄漏。为了提醒我这样做,我把这个日志放在我的 appdelegate 中:

if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");

If you need help finding the exact line, Do a Build-and-Debug (CMD-Y) instead of a Build-and-Run (CMD-R). When the app crashes, the debugger will show you exactly which line and in combination with NSZombieEnabled, you should be able to find out exactly why.

如果您需要帮助找到确切的行,请执行构建和调试 ( CMD-Y) 而不是构建和运行 ( CMD-R)。当应用程序崩溃时,调试器会准确地向您显示哪一行并结合 NSZombieEnabled,您应该能够确切地找出原因。

回答by epatel

About your array. The line

关于你的阵列。线

NSMutableArray *array = [NSMutableArray array];

does not actually give you a retained object but rather an autorelease object. It probably gets retained in the next line but then you should not release it in the third line. See this

实际上并没有给你一个保留的对象,而是一个自动释放的对象。它可能会保留在下一行,但你不应该在第三行释放它。看到这个

This is the fundamental rule:

You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.

这是基本规则:

如果您使用名称以“alloc”或“new”开头或包含“copy”(例如,alloc、newObject 或 mutableCopy)的方法创建对象,或者向其发送保留消息,则您获得对象的所有权。您有责任使用 release 或 autorelease 放弃您拥有的对象的所有权。任何其他时候你收到一个对象,你不能释放它。

回答by snez

In Xcode 4, you can enable Zombies by clicking on the Scheme dropdown (top left, right next to the stop button) -> Edit Scheme -> Diagnostics Tab -> Enable Zombie Objects

在 Xcode 4 中,您可以通过单击 Scheme 下拉列表(左上角,停止按钮旁边)-> Edit Scheme -> Diagnostics Tab -> Enable Zombie Objects 来启用 Zombies

回答by Darren

Xcode/gdb always breaks on EXC_BAD_ACCESS, you just need to work your way up the call stack to find the code that triggered it.

Xcode/gdb 总是中断EXC_BAD_ACCESS,您只需要沿着调用堆栈向上查找触发它的代码。

Note that these kinds of errors often occur with autoreleasedobjects, meaning that the ultimate cause of the problem won't be in the call stack that triggered EXC_BAD_ACCESS. That's when NSZombieEnabled and NSAutoreleaseFreedObjectCheckEnabled become helpful.

请注意,这些类型的错误经常发生在autoreleased对象上,这意味着问题的最终原因不会在触发EXC_BAD_ACCESS. 这就是 NSZombieEnabled 和 NSAutoreleaseFreedObjectCheckEnabled 变得有用的时候。

回答by Jonathan Moffatt

A new answer to an old thread... in XCode 4 the most effective way to diagnose EXC_BAD_ACCESS exceptions is to use Instruments to profile your app (from XCode click Product/Profile and choose Zombies). This will help you identify messages sent to deallocated objects.

旧线程的新答案...在 XCode 4 中,诊断 EXC_BAD_ACCESS 异常的最有效方法是使用 Instruments 来分析您的应用程序(从 XCode 单击 Product/Profile 并选择 Zombies)。这将帮助您识别发送到释放对象的消息。

回答by Frank

Another helpful approach is set breakpoints that will trigger directly after the exception occurs:

另一个有用的方法是设置断点,在异常发生后直接触发:

Open the breakpoints window (Run – Show – Breakpoints) and add two symbolic breakpoints called “objc_exception_throw” and “[NSException raise]"

打开断点窗口(Run - Show - Breakpoints)并添加两个名为“objc_exception_throw”和“[NSException raise]”的符号断点

From: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/

来自:http: //blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/

回答by Adam Eberbach

From the Stanford CS193P classes: if you add a breakpoint (manually, by editing breakpoints) for the symbolobjc_exception_throwyou can get a much better picture of what went wrong - letting things proceed to the point where the debugger halts by itself tends to obscure things and screw up the stack trace. When you halt in objc_exception_throw you can often look back to exactly what access/operation caused your problem.

来自斯坦福 CS193P 课程:如果您为符号添加断点(手动,通过编辑断点),objc_exception_throw您可以更好地了解出了什么问题 - 让事情进行到调试器自行停止的点往往会模糊事物并搞砸堆栈跟踪。当您在 objc_exception_throw 中停止时,您通常可以回顾到底是什么访问/操作导致了您的问题。

回答by Centurion

Just wanted to add for the others who are coming from a web, searching for solutions for the same error but with different mistake. In my case I got the same error when I tried to instantiate NSDictionary with typo in key name where I forgot to add "@" in front of my key:

只是想为来自网络的其他人添加,寻找相同错误但不同错误的解决方案。在我的情况下,当我尝试使用键名中的拼写错误实例化 NSDictionary 时,我遇到了同样的错误,我忘记在我的键前添加“@”:

NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil];

回答by Thomas Allenbaugh

I hope I didn't miss an identical answer, but I've found that it's possible for some projects to throw this error due to running on simulators for older iOS versions that may be incompatible with a project dependency or framework. I was chasing one of these down for too long before realizing it was just happening in the -older- simulator versions, like iPhone 4S, the app wasn't even supposed to try to support.

我希望我没有错过相同的答案,但我发现由于在可能与项目依赖项或框架不兼容的旧 iOS 版本的模拟器上运行,某些项目可能会抛出此错误。我追了很久,才意识到它只是在较旧的模拟器版本中发生,例如 iPhone 4S,该应用程序甚至不应该尝试支持。

Would have been nice to have gotten a more verbose error message, but I would imagine that's the responsibility of the framework where it originated... At any rate, this is a fairly common search landing and maybe this will help someone goofing up as badly as I found myself.

收到更详细的错误消息本来会很好,但我想这是它起源的框架的责任......无论如何,这是一个相当常见的搜索登陆,也许这会帮助某人搞砸同样严重正如我发现自己。

回答by user2387149

Before enabling zombies I recommend first get rid of all warnings (if you have any). Simple things like a non void function without a returncan cause this error. If you don't have warnings proceed as the other answers suggest.

在启用僵尸之前,我建议首先摆脱所有警告(如果有的话)。没有 a 的非 void 函数之类的简单事情return可能会导致此错误。如果您没有警告,请按照其他答案的建议进行。