被称为两次的Dealloc?

时间:2011-06-26 15:59:22

标签: objective-c ios ios4 memory-management

Resloved!

感谢Lone Gunman,这个问题是由于在发布之前没有将许多代表设置为nil的疏忽。

这是一个奇怪的...我熟悉基本的内存管理,但我认为我所看到的东西是不寻常的。这是一个小背景......

我有一个NavigationController,用于处理以下ViewControllers之间的导航:

主页 - >游戏 - >游戏

当运行代码时,它在离开游戏时会崩溃。在GameViewController中有一个类似于:

的dealloc方法
- (void)dealloc 
{
    [board release];
    [opponentsViewController release];
    [instructionsViewController release];
    [imgPicker release];
    [gameView release];
    [super dealloc];
}

当导航控制器返回游戏列表(从游戏中)时,它会抛出EXC_BAD_ACCESS。所以我提出了我可信赖的探查器并检查僵尸。唉,就像我预期的那样,一条消息被发送到一个解除分配的对象!深入挖掘我发现对象的历史中有3个条目:

  1. Board获取alloc(由Game的init方法调用)
  2. 董事会获释(由Game的dealloc方法调用)
  3. Board为Zombie'd(由Game的dealloc方法调用)
  4. 从UINavigationController setDisappearingViewController调用调用2和3。

    在我的dealloc方法中,我为每个释放调用设置了断点,当这样做时 - 发生[board release]调用,然后发生[opponentsViewController release]调用,然后再次发生[board release]调用。所以我看到dealloc方法没有完全完成并再次调用。

    可能导致这种情况的原因是什么?

    修改:这是GameViewController Implementation

    添加此游戏的游戏控制器代码:

    -(void) gotoGame:(int)tag {
    
        game = [[GameViewController alloc] init];
        [self.navigationController pushViewController:game animated:YES];
        [game release];
    
    }
    

    修改:这是GameViewController Header

2 个答案:

答案 0 :(得分:3)

我会尝试将你所有的ivar代表设置为nil(编辑:在dealloc中)。我对获取的结果控制器有类似的问题。无法在dealloc中将其委托设置为nil,并且在释放视图控制器时,核心数据堆栈仍然具有指向它的指针。

所以这是我的赌注,将ivar代表设置为dealloc中的nil,虽然我看不到你的标题知道你所遵循的协议是什么。

编辑:解释

设置委托实际上是为正在执行委托的对象提供指针(我相信它通常是指定的属性)。

@property (assign) delegate;

我将以我所遇到的问题为例。

所以假设你有一个视图控制器,它有一个fetchedResultsController作为一个ivar。设置FRC委托时:

fetchedResultsController.delegate = self;

并且视图控制器被释放,任何使用该指针的对象仍然认为它是活的。你会想到,因为FRC也会在dealloc中发布,你会很好(这就是为什么花了4天时间来解决这个问题:)),但有时候实现的其他部分也会使用你的委托。所以修复是:

-(void)dealloc
{
    self.fetchedResultsController.delegate = nil;
    [_fetchedResultsController release];
    [super dealloc];
}

注意:只要新工具可供所有人使用,您就不用再担心这些东西^ ^;

答案 1 :(得分:-3)

尝试

- (void) dealloc {
    if(game != nil){
     //release here
     [game release];
    }
    [super dealloc];
  }

顺便说一下,你似乎已经在头文件中声明游戏,并且在推送之后你正在释放它,并且在dealloc方法中你正在释放它。从dealloc方法中删除释放调用或更改这样的方法。

-(void) gotoGame:(int)tag {

    GameViewController *game = [[GameViewController alloc] init];
    [self.navigationController pushViewController:game animated:YES];
    [game release];

}

<强>更新

此外,您没有在任何地方使用该标签。为什么不像这样创建你的init方法

GameViewController *game = [[GameViewController alloc] initWithTag:tag];
[self.navigationController pushViewController:game animated:YES];
[game release];