【问题标题】:EXC_BAD_ACCESS when simply casting a pointer in Obj-C简单地在 Obj-C 中转换指针时的 EXC_BAD_ACCESS
【发布时间】:2010-05-15 12:10:06
【问题描述】:

经常访问,但第一次在 StackOverflow 上发帖,我希望你们能帮助我解决这个问题。我对 Obj-C 和 XCode 还很陌生,我面临着这个非常……奇怪的……问题。谷歌搜索没有出现任何东西。基本上,我在一条不执行任何取消引用或我可以看到的任何类似操作的线路上得到一个 EXC_BAD_ACCESS 信号。想知道你们是否知道在哪里寻找这个。我找到了解决方法,但不知道 为什么 这行得通...损坏的版本 barfs 所在的行是:

LevelEntity *le = entity;

我的访问信号不好。

这里是:

此版本有效

  NSArray *contacts = [self.body getContacts];
  for (PhysicsContact *contact in contacts)
  {
   PhysicsBody *otherBody;
   if (contact.bodyA == self.body)
   {
    otherBody = contact.bodyB;
   }
   if (contact.bodyB == self.body)
   {
    otherBody = contact.bodyA;
   }

   id entity = [otherBody userData];
   if (entity != nil)
   {
    LevelEntity *le = entity;

    CGPoint point = [contact contactPointOnBody:otherBody];
   }
  }

此版本无效

  NSArray *contacts = [self.body getContacts];
  for (NSUInteger i = 0; i < [contacts count]; i++)
  {
   PhysicsContact *contact = [contacts objectAtIndex:i];
   PhysicsBody *otherBody;
   if (contact.bodyA == self.body)
   {
    otherBody = contact.bodyB;
   }
   if (contact.bodyB == self.body)
   {
    otherBody = contact.bodyA;
   }

   id entity = [otherBody userData];
   if (entity != nil)
   {
    LevelEntity *le = entity;

    CGPoint point = [contact contactPointOnBody:otherBody];
   }
  }

这里,两个示例之间的唯一区别在于我枚举数组的方式。在第一个版本(有效)中,我使用 for (... in ...),而在第二个版本中,我使用 for (...; ...; ...)。据我所知,这些应该是一样的。

这真的让我很奇怪。任何人都有类似的经验或想法这里发生了什么?真的很棒:)

干杯, 亚历克斯

【问题讨论】:

  • 只是好奇——在这一行:CGPoint point = [contact contactPointOnBody:otherBody];您是在使用从代码示例中删除的点做某事,还是该调用实际上在联系或 otherBody 中设置了一些状态?
  • 我现在正在用它做一些事情——我在写示例的时候还没有,因为我发现在写引用的行和实际做一些有价值的事情之间发生了崩溃:)

标签: objective-c xcode memory-management


【解决方案1】:

首先,如果发生崩溃,则有回溯。始终为您的问题提供回溯(它将在调试器中并且可以复制/粘贴)。

正如 Vojito 所暗示的,此类崩溃的最常见原因与对象的过度释放有关。

在您的情况下,for(;;)for(... in ...) 实际上并不完全相同。后者很可能导致数组中的对象在迭代期间被保留或在检索时自动释放(我说“很可能”是因为我没有测试它——但它会解释这种行为)。

在您的代码中,您在迭代期间使用 otherBody = contact.bodyB 之类的语句修改对象图。如果这些语句中的任何一个恰好导致被迭代的数组中的一项从数组下释放出来,您就会看到崩溃。同样,如果对象图的修改导致contact.bodyAcontact.bodyB 成为悬空引用,您会看到崩溃。

所有只是一个有根据的猜测。发布回溯,并按照 Vojito 的建议,在启用了僵尸检测的 Instruments 中的分配工具下运行。

【讨论】:

  • 嗯,谢谢,听起来可能就是这样。看来我还有很多东西要学习内存管理!我来自 C# 背景,所以通常我习惯于免费处理所有这些东西。这很有趣,但很辛苦!
【解决方案2】:

堆栈变量,包括对象引用,不会自动初始化为 nil/0/NULL。尝试在其初始化程序中将 otherBody 设置为 nil:

PhysicsBody *otherBody = nil;

如果调试器说le 赋值是异常发生的地方,它实际上可能是它上面的语句,即[otherBody userData]。如果不初始化,otherBody 就是一个垃圾值。

【讨论】:

  • 虽然他确实应该将 otherBody 初始化为 nil,但他并没有在有效的和无效的两个中,这意味着(不知何故)似乎没有导致崩溃,除非 NSFastEnumeration 使用堆栈(我不相信它会这样)
  • 好点,谢谢。正如 Jared P 所说,我不认为这是导致崩溃的原因,尽管正如您所说,作为一般规则,这是一种很好的做法。谢谢:)
  • 由于涉及到NSFastEnumeration,这意味着两个例子的栈是完全不同的。因此,在一种情况下, otherBody (由于调用语义)可能永远不会是垃圾,并且实际上以 nil 值开始。 @AlexChilcott,您尝试过我的建议吗?从您的 cmets 看来,您似乎没有调查过这是否修复了它(或接受的答案的建议)。
  • 嗨杰森。感谢您的建议 :) 我确实在您的回答中提出了建议的更改,以防万一 otherBody 的分配确实没有被命中(不应该是这种情况,因为它被我的代码中其他地方的断言所涵盖)。但是,它并没有解决我的问题。我接受了 bbum 的回答,因为它给出了一个合理的解释(我还不能排除)为什么我会看到我的行为。我还没有深入了解它,所以我无法确定发生了什么,但 bbum 的回答是最有启发性的。
  • 不,所有逻辑都在同一个线程上。这是一个非常简单的应用程序,只是让我开始使用 Obj C 和 iPhone。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 2016-04-17
相关资源
最近更新 更多