释放实例变量会导致崩溃,但为什么呢?

时间:2010-03-04 01:51:21

标签: iphone objective-c memory-management

我有一个实例变量被定义并合成为如下属性:

@interface CardFrontView : GenericCardView {
    UIImage *_letterImage;
}

@property (nonatomic, retain) UIImage *letterImage;

@end

@implementation CardFrontView
@synthesize letterImage = _letterImage;
...

我在letterImage中设置了-init属性:

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self != nil) {
        NSString *filename = [[NSBundle mainBundle] pathForResource:@"fehu" ofType:@"png"];
        self.letterImage = [UIImage imageWithContentsOfFile:filename];
    }   return self;
}

然后,我在-dealloc中发布它,然后应用程序崩溃(EXC_BAD_ACCESS):

- (void)dealloc {
    [super dealloc];
    [_letterImage release];
}
但是,我无法弄清楚应用程序崩溃的原因。有没有人知道这笔交易是什么?

3 个答案:

答案 0 :(得分:20)

好的......从问题和评论中留下的线索中拼凑起来。

首先,这个:

- (void)dealloc {
    [super dealloc];
    [_letterImage release];
}

是错的,可能是本身崩溃的根源。您告诉拥有_letterImage的实例dealloc 然后告诉_letterImage释放。在调用[_letterImage release]时,包含_letterImage的对象已经死亡并且已经消失。

虽然可能导致崩溃,但可能不是(但仍应修复)。在评论中,你说:

  

当我移动[super dealloc]时,我发现失败消失了。   GenericCardView没有什么奇怪的   所有(只是一些预配置   是几种不同的常见的   Card S)。所以,我不知道为什么会这样   发生了,这一切都让我相当   不舒服。

所有dealloc方法都应该始终调用[super dealloc];作为 -dealloc方法实现中的最后一行代码 。始终无例外*。

当您移除对[super dealloc]的来电时,任何内容都会开始有效,100%保证会在您的代码中显示错误。

在这种情况下,我不会对您的GenericCardView类错误地管理实例变量感到惊讶。我首先回顾一下该类dealloc方法中发布的所有变量,以确保它们首先得到正确管理(同时还要检查dealloc的实现本身)。

无论如何,这有点像过度释放问题。将代码恢复到崩溃发生的状态,然后使用Instrument的僵尸检测工具查看它们是否捕获崩溃并识别过度释放的对象。即使真正的原因只是 ,但您没有在[super dealloc]方法中最后调用dealloc,请确认 案件应该提高你的舒适度。

*实际上有一个例外;当你编写自己的根类时。但这种情况非常罕见,以至于不计算在内。 (快乐,盖伊?:)

答案 1 :(得分:3)

除了要求您发布的约定或其他方面,您的代码的真正问题是[super dealloc]后跟其他任何内容。调用该方法后,您不能再在对象中执行任何操作。

相反,首先进行本地清理,只有在完成后才调用超级。

它基本上与init方法相反,在超级初始化调用之前你不能做任何有用的事情。

亚历

答案 2 :(得分:1)

您是否曾在代码中的任何其他位置访问此内容?我唯一能想到的就是它被释放到其他地方而没有先被保留。

它也可能 - 虽然我非常怀疑这一点 - 是因为你的[super dealloc]电话是第一次,而不是最后一次。虽然把它放在最后是好的做法,但我觉得它没有任何功能差异 - 你在超类中做了什么奇怪的事情可能会导致它?