假设我有以下代码:
@property (nonatomic, retain) *SomeObject foo;
@property (nonatomic, retain) *SomeObject bar;
@synthesize foo, bar;
self.foo = [[SomeObject alloc] init];
self.bar = [[[SomeObject alloc] init] autorelease];
if (self.foo) {
[self.foo release];
self.foo = nil;
}
if (self.bar) {
[self.bar release];
self.bar = nil;
}
我的self.bar出现内存泄漏。我不确定为什么,但我认为这是因为在调用[self.bar release]之后,对象self.bar指向自动释放。当我把self.bar排除在外时,我们尝试在前一个对象(已经自动释放)上调用release,这会产生错误。它是否正确?还有,其他内存泄漏,也许与foo? 什么是正确的解决方案?
我应该删除发布语句并且只删除这两个属性吗?
答案 0 :(得分:2)
您应该直接使用访问者:
self.foo = [[[SomeObject alloc] init] autorelease];
self.bar = [[[SomeObject alloc] init] autorelease];
if (self.foo) {
self.foo = nil;
}
if (self.bar) {
self.bar = nil;
}
因为合成属性访问器生成执行引用计数操作的代码。
永远不要使用[someObject.someProperty release]
格式。
你不应该使用访问器的唯一地方是部分构造的状态(即初始化和dealloc
)。在此上下文中,使用直接访问:[ivar release], ivar = nil;
。
答案 1 :(得分:1)
您的代码中有3个地方错误:
@property (nonatomic, retain) *SomeObject foo;
@property (nonatomic, retain) *SomeObject bar;
self.foo = [[SomeObject alloc] init]; // WRONG 1
self.bar = [[[SomeObject alloc] init] autorelease];
if (self.foo) {
[self.foo release]; // WRONG 2
self.foo = nil;
}
if (self.bar) {
[self.bar release]; // WRONG 3
self.bar = nil;
}
在任何方法中,除非直接在对象上设置实例变量,否则必须平衡保留和释放。您没有直接在此处设置任何实例变量。您正在使用属性(方法调用)。
1是错误的,因为alloc
返回一个保留实例(你(这个方法)“拥有”它,因此你必须在它超出你的范围之前释放它)。您将它传递给方法(属性设置器),然后您不再具有对它的引用。因此它被泄露了。
2和3是错误的,因为你发布的是你不拥有的东西。属性访问是方法调用,普通方法调用不返回保留实例。
错误1和2碰巧平衡 - 有很多错误,他们碰巧以错误的方式取得了正确的结果。错误3应该导致程序崩溃,因为你过度释放。