更具体,一般的Objective-C内存管理

时间:2009-10-22 22:29:12

标签: objective-c memory-management

我读到的关于objective-c内存管理的所有内容都让人觉得难以置信。用大家的意思来说:“释放你分配,保留或复制的任何内容”。但我认为还有一些更具体的案例并不那么明确。以下是一些示例情况。每种方法的正确程序是什么:

情况#1:

Foo *foo = [[foo alloc] init];
Foo *fooToo = [[[foo alloc] init] autorelease];

foo = fooToo;

在将foo分配给fooToo之前是否需要释放它?

情况#2 当我做以下事情时,我似乎遇到了很多崩溃: (.h和.m为了方便而混在一起)

Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;

-(id)init{
self = [super init];
}

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

我经常被告知“总是以dealloc释放你为什么设置保留属性”。但如果像我所示的那样完成,这将会崩溃。

情况#3 类似的情况也会崩溃: (.h和.m为了方便而混在一起)

Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;

-(id)init{
self = [super init];
self.foo = nil;
}

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

由于某些原因,当我的代码归结为dealloc时,foo不是== nil。

情况#4 最后,只是一个问题,人们在决定

时使用什么样的一般思维过程
 self.foo = bar;

 foo = bar;

当宣布foo与上述情况相同时? self.foo只是另一种编码方式:

foo = [bar retain];

2 个答案:

答案 0 :(得分:6)

情况#1:

是的,您需要在失去对它的引用之前释放foo。鉴于您已分配它,您有责任释放它。如果您在发布之前重新分配foo,则无法再释放它!

情况#2:

dealloc的正确实施是:

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

dealloc方法需要调用超级dealloc方法而不是release方法。此外,您需要在调用[super dealloc]

之前先释放字段

情况#3: 与情况#2相同。

情况#4:

我总是喜欢使用self.foo = bar,因为如果需要,它会自动执行以下步骤:

  1. 发布foo
  2. 保留bar
  3. foo分配给bar
  4. 作业foo = barfoo = [bar retain]不会释放foo的上一个对象。

答案 1 :(得分:4)

等待。停止。 Msaeed的答案是正确的,逐行的,但没有强调真正的问题。

你要么像计算机一样思考,要么每行代码都假设太多魔法。

请不要把它视为一种侮辱 - 这是一个非常容易犯的错误,这是一个几乎每个程序员在新环境中做出的错误(我在开始使用Objective-C时做了一些非常神奇的假设) 1989)。

让我们重新考虑一下情况。

情况#1: ...删除不相关的代码...

foo = fooToo;

这是一个简单的任务。无论在此之前包含的foo - 对您案例中的对象的引用 - 现在都会被fooToo的值覆盖。没有魔力。没有额外的方法执行或涉及的代码行。

如果foo包含对该行代码保留对象的引用。引用将被覆盖。如果在覆盖引用之前需要release foo,请执行此操作,但这与分配正交。

情况#2: ...删除不相关的代码...

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

玩电脑;你要求super dealloc然后假设一个实例变量在super被释放后有效。坏消息。吊杆。

这里没有魔力。 foo是对实例变量的引用 self。 -dealloc会破坏自我,因此foo不再有效。

(我相信静态分析仪会抓住它。如果没有,它应该。)

情况#3:

见#2。这是完全相同的问题。您正在访问不再有效的实例的实例变量。

情况#4:

self.foo = bar;

完全相同:

`[self setFoo:bar];

(禁止任何背叛者=恶作剧)

因此,关键的区别在于-setFoo:的实现 - 手写或@synthesized。在你的情况下,它retain s吧。这与foo = bar;不同,因为没有保留发生;它只是对bar的引用的赋值。

我强烈建议您重新访问Objective-C介绍文档。这会有所帮助。但是,我还鼓励您退后一步,真正思考上述情况中每行代码的作用。没有魔力,实际行为非常简单。