我对此感到很困惑。我相信我正在以正确的方式管理内存,但执行代码表明我正在双重释放该对象。这是代码,然后我将解释发生了什么。
@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”错误,并且当它尝试dealloc时应用程序崩溃。我已经跟踪了在Layout类的dealloc方法中释放someDelegate对象的崩溃。如果我留下评论,那么应用程序工作正常。
有人可以解释一下为什么会发生这种情况,因为它似乎与我在Objective-C中读到的有关内存管理的内容相违背。
请注意代码示例实际上是有效的,但是我的代码不遵循示例。我的实际SomeObject内部是否会出现导致自动释放的内容?
提前致谢。
答案 0 :(得分:3)
首先,请返回并重新阅读memory management rules,以确保您在其他地方使用代理时不会遗漏任何明显的内容。
接下来,打开NSZombieEnabled(在可执行设置的Arguments面板中,添加一个环境变量NSZombieEnabled设置为YES)。
然后在你的delagate中添加一个dealloc方法,如果它还没有(请确保你调用[super dealloc]!)并在那里放置一个断点 - 这将告诉你何时你的delagate被解除分配会告诉你当它被释放时。
或者,将普通的释放/自动释放方法添加到您的委托类中,除了调用之外什么都不做,然后断点它们,这将告诉您何时释放它。
三个最终评论:在Objective C / Cocoa的标准命名约定中,你应该有小写参数字段,即它应该是:
- (id)initWithFrame:(CGRect)aRect cols:(NSUInteger)Cols rows:(NSUInteger)Rows;
当您的ivar和属性名称相同时,很容易意外使用错误的名称,因此我建议使用不同的ivar名称和属性名称以避免混淆,使用像Apple这样的_前缀或其他一些前缀为了避免与Apple混淆:
id<SomeDelegate> _someDelegate;
@synthesize someDelegate = _someDelegate;
Apple建议不要在init / dealloc中使用setter / getter,所以你的init代码应该是:
_someDelegate = [[SomeObject alloc] initWithCols:cols Rows:rows];
答案 1 :(得分:2)
正如评论中所提到的,问题似乎没有出现在发布的代码中。
我可以要求提供更多信息,但我坚定地教导一个人去钓鱼营地......
崩溃 - 释放通常会产生误导,因为各种优化 - 通常是尾部调用优化 - 会使崩溃发生在实际调用崩溃之前的一两帧。当崩溃发生时,堆栈上没有足够的信息来确定罪魁祸首。
每当你怀疑-release或-dealloc中有任何类型的崩溃时,请立即打开Zombies。这可以通过Instruments或环境变量完成,也可以在程序执行的早期调用Foundation中的函数。
在开发环境附带的文档中搜索“Zombies”或“NSZombie”(更像是“教人钓鱼”的事情)。
答案 2 :(得分:0)
问题是一个MutableArray深入一个通过工厂创建的子类(自动释放),但我也发布了。不幸的是,崩溃不会指示哪个继承的dealloc导致崩溃,只是停止在第一个被覆盖的dealloc上。
Zombie的事情有点帮助,因为它告诉我阵列是罪魁祸首,但没有多少。我认为NSZombie还有更多需要更多经验来充分利用它。