是什么原因导致“EXC_BAD_ACCESS”当调用选择器时?
当 Objective-C 中调用选择器时,应用程序崩溃,导致调试堆栈指向选择器,这是什么原因?据我了解,这是由于内存错误而发生的。但是,我向其发送命令的对象和参数(数组)都是有效的。我可以这么说,因为当鼠标悬停在 Xcode 中时,这两个对象会显示内存位置以及其他信息。
由于跟踪在此选择器处结束,我不知所措。当堆栈指向具有有效对象参数的选择器时,我从未见过此错误。
此外,该选择器被频繁调用。它总是处理相同类型的对象,并且在我崩溃之前没有任何迹象表明存在异常行为。
这种崩溃并不常见,每 10 分钟或更短时间就会发生一次。
由于我是一名新手程序员,选择器内的代码可能有问题。我经常这样比较对象指针:
if (thisObject.pointerToSomeObject == nil) { //do stuff...
我开始怀疑这是否是正确的 Objective-C 编程,但话又说回来,代码在大多数情况下都有效。有没有我不知道的极端情况?
附加信息: 我使用的是cocos2d版本1.0.0,Xcode 4.1。在 iPad 模拟器上进行测试。
任何帮助都是值得赞赏的,甚至相关调试文章的链接也会有所帮助。
编辑
开发:
指向选择器的默认调试线程,如果存在错误的访问错误,则可能意味着错误的访问发生在该选择器的执行中。可以使用 NSZombies 进行进一步调试以找到确切的行。
所以,开启 NSZombies 后,问题就更加详细地暴露出来了。 (感谢 @Lou Franco 提供的错误访问教程)
现在,什么会导致:
if ([thisZombie target] == nil)
评估为“否”,但在访问 [thisZombie target]
中的整数时抛出错误访问? target
是一个指向 NSObject(僵尸化)的指针
else {
int diffx = [thisZombie x] - [[thisZombie target] x];
// ^^ ----- bad access here
** 编辑 2 **
语法或短路评估一定有问题:
if (!thisZombie.target && thisZombie.leader && !thisZombie.leader.dead)
thisZombie.leader.dead 停止线程: “ * -[僵尸死亡]:消息发送到已释放的实例 0x2108f0”
我想我应该提到这个游戏有“僵尸”,不要与“NSZombie”混淆
所以,程序评估“thisZombie.target”为“true” 但是当我去访问“thisZombie.target.x”时,程序停止执行。
为什么?
编辑3
大家好, 我想再次感谢大家提出的有益的意见和建议。 我决定通过彻底改变我的僵尸跟随领导者的方式来解决这个问题。
我仍然不知道什么会导致如上所述的评估,但不再需要答案。
When a selector is called in Objective-C, and the app crashes, resulting in the debug stack pointing to a selector, what is the cause of this? From what I understand, this happens as a result of a memory error. However, both the object I am sending the command to, and the parameter (an array) are valid. I can tell because these two objects reveal memory locations as well as other info when moused over in Xcode.
Since the trace ends at this selector, I am at a loss. I have never seen this error when the stack points to a selector with valid object parameters.
Furthermore, this selector is called frequently. It always deals with the same types of objects, and there is nothing to suggest abnormal behaviour before my crash.
This crash is infrequent, happening every 10 minutes or less.
Since I am a novice programmer, there is likely something wrong with the code inside the selector. Often I compare object pointers like so:
if (thisObject.pointerToSomeObject == nil) { //do stuff...
I am beginning to doubt this is proper Objective-C programming, but then again, the code works most of the time. Is there a corner case I am not aware of?
Additional Info:
I am using cocos2d version 1.0.0, Xcode 4.1. Testing on the iPad simulator.
Any help is appreciated, even links to relevant debugging articles would be helpful.
EDIT
Developments:
A default debug thread pointing to a selector, with a bad access error can mean that the bad access is happening within that selector's execution. It is possible to turn on further debugging with NSZombies to find the exact line.
So, after turning on NSZombies, The problem is revealed in greater detail. (Thanks @Lou Franco for that bad access tutorial)
Now, what would cause:
if ([thisZombie target] == nil)
to evaluate NO, but throw a bad access when accessing an integer in [thisZombie target]
?
The target
is a pointer to an NSObject (zombified)
else {
int diffx = [thisZombie x] - [[thisZombie target] x];
// ^^ ----- bad access here
** EDIT 2 **
There must be something wrong with the syntax, or the short-circuit evaluation:
if (!thisZombie.target && thisZombie.leader && !thisZombie.leader.dead)
thisZombie.leader.dead stops the thread with:
" * -[Zombie dead]: message sent to deallocated instance 0x2108f0"
I suppose I should mention that this game has "Zombies" which are not to be confused with the "NSZombie"
So, the program evaluates "thisZombie.target" as "true"
but when I go to access "thisZombie.target.x" the program ceases execution.
Why?
EDIT 3
Hi Everyone,
I'd like to thank you all again for your helpful comments and suggestions.
I decided to solve this by completely changing how my zombies follow their leaders.
I still have no Idea what would cause evaluation as described above, but the answer is no longer required.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我写这篇博客是为了帮助理解和调试 EXC_BAD_ACCESS
http://loufranco.com/blog/ files/Understanding-EXC_BAD_ACCESS.html
按照容易程度的顺序
运行构建并分析 - 您是否获得了干净的构建?看看它说的是什么,但您现在可以忽略泄漏问题 - 查找向已发布对象发送消息的问题
使用 NSZombiesEnabled 运行 - 这使得对象永远不会释放,然后如果将消息发送到对象则抱怨keepCount 为 0。
启用 Guard Malloc,然后使用特殊的GDB命令检查堆的完整性。问题是你需要在崩溃之前逐步执行此操作以找到真正的问题。 但它可能会在更接近您的问题的其他地方崩溃
尽管编辑:根据您上面的信息, 。您释放了
thisZombie.leader
,但没有将其设置为 nil。也许,您忘记让这个 Zombie 保留它,所以它被提前释放了。如果存在循环引用(僵尸指向领导者,领导者指向后面),这可能会很棘手。如果它不是循环的,请记住保留您设置属性指向的任何对象(如果您使用保留属性并记住始终使用属性语法,则自动保留)
在 iOS 上的 Objective-C 中,什么是使用合成 getters 时“self.foo”和“foo”之间的(风格)区别?
I wrote this blog to help understand and debug EXC_BAD_ACCESS
http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html
In order of easiness
Run a Build and Analyze -- do you get a clean build? Look at what it's saying, but you can ignore leak problems for now -- look for problems of sending messages to released objects
Run with NSZombiesEnabled -- this makes objects never deallocate, and then complain if a message is sent to an object with retainCount of 0.
Enable Guard Malloc and then use the special GDB commands to inspect the integrity of the heap. The problem is that you need to step through and do this before you crash to find the real problem. It might crash somewhere else closer to your problem though
EDIT: based on your information above. You deallocated
thisZombie.leader
, but you didn't set it to nil. Probably, you forgot to have thisZombie retain it, so it got deallocated early.This could be tricky if there are circular references (zombies point to leaders and leaders point back). If it isn't circular, remember to retain any object you set a property to point to (automatic if you use retained properties and remember to always use the property syntax)
In Objective-C on iOS, what is the (style) difference between "self.foo" and "foo" when using synthesized getters?
即使对象显示内存位置并不意味着它是有效的。它可能被释放,而你只是持有指向垃圾的指针。
Even if object reveal memory location doesn't mean it is valid. It maybe freed and you're just holding pointer to the garbage.
您需要检查您的数组或其他变量是否已初始化。使用 NSLog 或断点可以帮助您找到导致此错误的确切变量。如果是因为传递或返回某些参数而导致的,那么Max建议的原因也是有效的。
如果您可以发布代码,将有助于找到确切的问题。
You need to check if your array or some other variable has been initialized or not. Using NSLog or breakpoints can help you find the exact variable causing this error. In case it is because of some parameter passed or returned, then the reason suggested by Max is also valid.
It would help to find the exact problem if you can post the code.