【问题标题】:Why is my pointer being changed?为什么我的指针被改变了?
【发布时间】:2011-11-12 14:31:57
【问题描述】:

长话短说,我正在开发一个简单的游戏,我有一个 Game 对象来跟踪当前的游戏状态,以及一些以后有用/需要的其他东西。其中之一是对加载游戏的UIViewController 的引用,它被简单地声明为对象的属性:

@interface Game : NSObject {
    //ivars
}

@property (nonatomic, retain) myViewController* viewController;

该属性的 getter/setter 是使用 @synthesize viewController 生成的,看起来一切正常。

现在只有两条路径可以访问此属性,当游戏获胜和失败时。 “游戏失败”路径工作正常。 “游戏获胜”路径导致了一个奇怪的错误,其中viewController 指针的值似乎被垃圾覆盖。

为了弄清楚发生了什么,我如下覆盖了getter和setter:

- (myViewController*) viewController {
    NSLog(@"Getting");
    return viewController;
}

- (void) setViewController:(myViewController*)controller {
    NSLog(@"Setting");
    viewController = controller;
}

...并在里面设置断点(我知道我没有保留视图控制器是我的设置器,但这不是问题;视图控制器保留在堆栈上,实际上不需要由 @987654327 保留@)。这是我在 GDB 中得到的:

//first call to setter
po controller
<myViewController: 0x9208130>

//call to getter on the "game is lost" path
(gdb) po viewController
<myViewController: 0x9208130>

//call to setter, starting a new game from the same view controller
(gdb) po controller
<myViewController: 0x9208130>

//call to getter on the "game is lost" path
(gdb) po viewController
0xbea2222c does not appear to point to a valid object.
(gdb) print viewController
$1 = (myViewController *) 0xbea2222c

所以在某些时候,指针的值从0x9208130 更改为0xbea2222c,但我不知道在哪里。除了在游戏开始时调用 setter 之外,没有任何代码可以分配给 viewController 属性(或其支持 ivar)。然而,显然有些东西在“游戏获胜”路径上用垃圾覆盖了值。

这可能是缓冲区溢出问题吗?如果是这样,有什么好的方法可以追踪它?

编辑

我添加了第二个指针(作为另一个类中的 ivar),我在游戏开始时将其设置为 game.viewController 的值,并将此指针用于“游戏获胜”路径有效。所以在我看来,有些东西正在破坏原始指针。但是,仍然不知道是什么。

【问题讨论】:

  • 垃圾收集器将对象移动到不同的地址,但这不应该影响您的引用,这不会受到影响。
  • @Ryan - 我没有使用自动垃圾收集。即使垃圾收集器移动了对象并更新了指针,它仍然应该指向同一个对象。根据 GDB,0xbea2222c 上的任何东西都不再是同一个对象。另外为什么垃圾收集器只会在“游戏获胜”路径上触发?
  • 很抱歉这个简单的评论,但你已经完成了泄漏仪器分析的事情,对吧?这告诉了你什么?
  • 二分查找,用 log(n) 时间找到违规行。 :D
  • @bdares - 这不是需要先按可疑的错误程度对所有行进行排序吗?当然,这只需要完成一次,但完成它需要超过 log(n) 时间。

标签: iphone objective-c pointers properties cocos2d-iphone


【解决方案1】:

你的二传手错了。它应该是:

- (void) setViewController:(yeticonfettiViewController*)controller {
    NSLog(@"Setting");
    [viewController autorelease];
    viewController = [controller retain];
}

否则你永远不会保留控制器,它很可能会被垃圾回收。

【讨论】:

  • 是的,这个症状非常适合。
  • 我将在我的问题中提到这不是问题(使用执行保留的自动生成的设置器也会发生同样的事情)。视图控制器始终保留,因为它仍然在活动视图控制器的堆栈上。 Game 对象中的属性实际上并不需要首先声明为 retain。问题绝对不是UIViewController 过早地释放/释放。这是我检查的第一件事。
【解决方案2】:

根据您发布的信息,似乎没有足够的数据来诊断问题。

如果你想进一步调试这个问题,我建议在指针 ivar 的内存地址上设置一个断点。这样,如果它在您的 setter 使用之外发生了某种更改,您将收到通知。

您可以通过在创建游戏对象期间的某个时间点中断并在游戏对象的控制器 ivar 上选择“观察变量”来完成此操作。

另外,asksol 有一个很好的例子,可以在 Xcode 外部以类似的方式使用 gdb 来回答另一个问题 here

【讨论】:

  • 谢谢,这让我解决了问题。这实际上是一个缓冲区溢出问题。基本上我有一组按级别索引的状态信息(每个级别一个条目)。在“游戏获胜”路径上,级别增加超过最后一个实际级别,并且对该状态数组的访问超出范围。修复了它并解决了问题。
猜你喜欢
  • 1970-01-01
  • 2021-05-04
  • 2012-10-04
  • 2016-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-29
  • 1970-01-01
相关资源
最近更新 更多