2009-06-29 37 views
3

我真的很困惑这一点。我相信我正在以正确的方式管理内存,但执行代码表明我正在双重释放对象。这里是代码,然后我会解释发生了什么。双重发布时不应该发生

@protocol SomeDelegate <NSObject> 
@required 
- (id)initWithCols:(NSUInteger)Cols Rows:(NSUInteger)Rows; 
@end 


@interface SomeObject : NSObject <SomeDelegate> { 
} 
- (id)initWithCols:(NSUInteger)Cols Rows:(NSUInteger)Rows; 
@end 


@interface Layout : UIView { 
    id<SomeDelegate> someDelegate; 
} 
@property(retain) id<SomeDelegate> someDelegate; 
- (id)initWithFrame:(CGRect)aRect Cols:(NSUInteger)Cols Rows:(NSUInteger)Rows; 
@end 


@implementation Layout 
@synthesize someDelegate; 
- (id)initWithFrame:(CGRect)aRect Cols:(NSUInteger)Cols Rows:(NSUInteger)Rows { 

    if(self = [super initWithFrame:aRect]) { 
    cols = Cols; 
    rows = Rows; 
    id<SomeDelegate> delegate = [[SomeObject alloc] initWithCols:cols Rows:rows]; 
    [self setSomeDelegate:delegate]; 
    //[delegate release]; 
    } 
    return self; 
} 

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

@end 

现在,当我去掉了 “// [委托释放];”在Layout类的构造函数中,然后我得到一个“EXC_BAD_ACCESS”错误,当它尝试释放时,应用程序崩溃。我已经将崩溃追溯到Layout类的dealloc方法中释放someDelegate对象。如果我留下评论,那么应用程序工作正常。

有人能解释为什么会发生这种情况,因为它似乎违背了我在Objective-C中有关内存管理的所有内容。

只是说明该代码示例实际工作,但是我的代码不符合该示例。我的实际SomeObject中是否会引起autorelease?

在此先感谢。

+0

出于好奇,如果将“委托”变量重命名为其他内容,会发生什么?我知道这应该不重要,但我记得按照同样的方法在cocoa-dev邮件列表中阅读了一些内容;奇怪的行为与某些变量名称。 UIView有它自己的委托,我想知道它是否与此有关。 – dreamlax 2009-06-29 22:48:44

+0

好想法,但不幸的是我尝试将它重命名为委托,它仍然有释放问题。 – 2009-06-29 23:24:09

回答

3

首先,回去重读memory management rules只是为了确保在其他地方使用委托时不会漏掉任何明显的东西。

接下来,打开NSZombieEnabled(在您的可执行设置中,Arguments面板中,添加一个NSZombieEnabled设置为YES的环境变量)。

然后,dealloc方法添加到您的delagate,如果它没有一个已经(确保你调用[超级的dealloc]!),换上有一个破发点 - 这会告诉你,当你delagate被释放,这将告诉你什么时候被释放。

或者,向您的委托类添加简单的发布/自动释放方法,这些方法除了调用通过之外什么都不做,然后断点它们,这会告诉你它何时被释放。

三篇最后评论:在目标C /可可标准的命名规则,你应该有小写参数字段,也就是说,它应该是:

- (id)initWithFrame:(CGRect)aRect cols:(NSUInteger)Cols rows:(NSUInteger)Rows; 

当你的伊娃和财产具有完全相同的名称,这是非常容易不小心用错了一个,所以我建议使用不同的伊娃名和属性名以避免混淆,无论是使用_前缀像苹果,或一些其他的前缀以避免混淆与苹果还有:

id<SomeDelegate> _someDelegate; 

@synthesize someDelegate = _someDelegate; 

苹果推荐我们荷兰国际集团在初始化/ dealloc的制定者/吸气,让您的初始化代码应该是:

_someDelegate = [[SomeObject alloc] initWithCols:cols Rows:rows]; 
2

正如评论中提到的那样,问题似乎并未出现在发布的代码中。

我可以要求更多的信息,但我在授人以鱼阵营很坚决....

在-release崩溃往往会在各种优化误导 - 尾调用优化,通常 - 会使它看起来像崩溃发生在实际呼叫之上的一帧或两帧。发生崩溃时,堆栈中没有足够的信息来真正识别罪魁祸首。

每当您怀疑在-release或-dealloc中有任何类型的崩溃时,立即打开僵尸。这可以通过仪器或通过环境变量来完成,或者在程序执行的早期通过在基金会中调用函数来完成。

搜索开发环境中包含的文档中的“僵尸”或“NSZombie”(这更多的是“教人钓鱼”的东西)。

0

的问题是一个MutableArray深这是通过工厂创建一个子类(自动释放),但我也释放了。不幸的是,崩溃并不能指示哪个继承的dealloc导致了崩溃,而只是停在第一个重载的dealloc上。

僵尸的事情有所帮助,它告诉我一个数组是罪魁祸首,但没有其他许多。我认为NSZombie更多,需要更多经验才能充分利用它。