1

可以说我有以下代码:

@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 设为 nil 时,我们尝试在前一个对象(已自动释放)上调用 release,这会产生错误。这个对吗?此外,是否还有其他内存泄漏,也许是 foo?什么是正确的解决方法?

我应该删除发布声明并将两个属性都归零吗?

4

2 回答 2

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;.

于 2012-11-01T23:14:54.873 回答
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 应该会导致程序崩溃,因为您过度释放。

于 2012-11-02T09:43:02.077 回答