调用选择器时导致“EXC_BAD_ACCESS”的原因是什么?

时间:2011-08-11 18:40:24

标签: objective-c ipad crash cocos2d-iphone 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)

评估NO,但在访问[thisZombie target]中的整数时抛出错误的访问权限? target是指向NSObject(zombified)

的指针
else {

  int diffx = [thisZombie x] - [[thisZombie target] x];
  //                                          ^^ ----- bad access here

**编辑2 **

语法或短路评估一定有问题:

if (!thisZombie.target && thisZombie.leader && !thisZombie.leader.dead)

thisZombie.leader.dead使用以下命令停止线程: “ * - [Zombie dead]:发送到解除分配的实例0x2108f0的消息”

我想我应该提一下这个游戏有“僵尸”,不要与“NSZombie”混淆

因此,程序将“thisZombie.target”评估为“true” 但当我去访问“thisZombie.target.x”时,程序停止执行。

为什么?


编辑3

大家好, 我再次感谢大家的有益评论和建议。 我决定通过彻底改变我的僵尸跟随领导者的方式来解决这个问题。

我仍然不知道如上所述会导致评估的原因,但不再需要答案。

3 个答案:

答案 0 :(得分:1)

我写这篇博客是为了帮助理解和调试EXC_BAD_ACCESS

http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html

为了方便

  1. 运行构建和分析 - 你得到一个干净的构建?看看它在说什么,但你现在可以忽略泄漏问题 - 寻找向已发布对象发送消息的问题

  2. 使用NSZombiesEnabled运行 - 这会使对象永远不会释放,然后在向retainCount为0的对象发送消息时进行投诉。

  3. 启用Guard Malloc,然后使用特殊的GDB命令检查堆的完整性。问题是你需要在崩溃之前单步执行此操作以找到真正的问题。尽管

  4. ,它可能会在更接近你问题的地方崩溃

    编辑:根据您的上述信息。您已取消分配thisZombie.leader,但未将其设置为nil。也许,你忘了让这个僵尸保留它,所以它很早就被解除了分配。

    如果有循环引用(僵尸指向领导者和领导者指回),这可能会很棘手。如果它不是循环的,请记住保留您设置属性的任何对象以指向(如果您使用保留属性并且记得始终使用属性语法,则自动)

    In Objective-C on iOS, what is the (style) difference between "self.foo" and "foo" when using synthesized getters?

答案 1 :(得分:0)

即使对象显示内存位置并不意味着它有效。它可能被释放,你只是拿着指向垃圾的指针。

答案 2 :(得分:0)

您需要检查您的数组或其他变量是否已初始化。使用NSLog或断点可以帮助您找到导致此错误的确切变量。如果是因为传递或返回了某些参数,那么Max建议的原因也是有效的。

如果您可以发布代码,那将有助于找到确切的问题。