2009-04-16 13 views
2

私はあなたがしなければあなたが最も確かにメモリリーク持って、次のことを知っている:これは客観的なメモリリークですか?

id foo = [[NSObject alloc] init]; 
foo = nil; 

をしかし、あなたはself.foo、保持してプロパティを何を使っている場合は?あなたのコードは、次のようになります。

アクセサーがメモリを解放してからnilに設定するとメモリリークが発生しますか?

答えて

4

self.foo = nilにはメモリリークがここにありません

[nil retain] 
[foo release] 
foo = nil 

につながるでしょう。

2

いいえ、2番目の例はメモリリークではありません。実際には、それは私のdeallocメソッドのretainプロパティを処理する方法です。それはちょうど多くのクリーナーです。

あなたは注意する必要があり唯一のことは、あなたがオブジェクトをダブル保持し、メモリリークになってしまいます

self.foo = [[NSObject alloc] init]; 

か、他に書くことがわからない行っています。

+4

deallocのプロパティを使用することは、別のivar(すでにリリースされているかもしれない)を変更するためにアクセサーメソッドが変更された場合には、通常避けてください。私はちょうどリリースを代わりに使用します。 –

+0

@Alex:優秀な警告の場合は+1、deallocメソッドではself.foo = nilを使用することを提案する場合は-1です! –

+2

@eJames self.foo = nilは、元々deallocメソッドでそれを行うことを推奨していた方法であり、サンプルコードのどこにでもあります。 –

0

あなたは本質的にセッターを使用し、無料でメモリ管理を取得しているとは思わないと思います。self.foo = nil

1

プロパティは、あなたのコードを代入のように見せますが、現実にはObj-C 2.0より前に書いた従来のアクセサメソッドと同じです。プロパティを使うとObj-Cは宣言で指定したキーワードを使用する代わりに(@synthesizeを使用し、独自のアクセサメソッドを作成しないと仮定して)、舞台裏でアクセサーメソッドを生成しています。

1

いいえ、メモリリークはありません。あなたの第二の例のコードは

foo = [[NSObject alloc] init]; 
[nil retain]; 
[foo release]; 
foo = nil; 

と論理的に等価である@synthesizedセッターが

- (void)setFoo:(id)newFoo { 
    [newFoo retain]; 
    [foo release]; 
    foo = newFoo; 
} 

にlogicall同等であるので、それは直接fooを設定すると、おそらくあなたが外でやりたいものではないことは注目に値しますinitメソッド。 fooに値を直接割り当てると、willChangeValueForKey:/didChangeValueForKey:ペアで割り当てをラップする必要があります のすべての変更を期待して、setFoo:メソッドをオーバーライドすると、サブクラスの動作が破損します。セッターを通過する。

setFoo:メソッドまたはサブクラスのオーバーライドsetFoo:メソッドが副作用を持つか、インスタンスが完全に初期化されていることが原因で、initメソッドで直接fooに割り当てられます。

同様に、同じ理由で-deallocメソッドでself.foo = nil;ではなく[foo release]を使用します。

1

これまでの回答すべては、2番目の例の1行目の "foo"がfooプロパティの背後にあるインスタンス変数であると仮定しています。これがデフォルト動作です。

最初の行に割り当てられているfooがローカル変数である場合、fooプロパティは無関係であり、メソッドの後半でオブジェクトを解放しない限り、オブジェクトはリークします。

fooがインスタンス変数であるが、fooプロパティが実際には異なるインスタンス変数またはインスタンス変数によってサポートされていない場合は、(a)メンテナンスが難しいコードを記述しています。(b)漏れである。

最後に、以前の回答をエコー:foofooプロパティをバックアップするインスタンス変数がある場合、これはあなたが2行目に呼び出すsetFoo:メソッドは、オブジェクトを解放しますので、あなたはfooに入れている、リークではありません最初の行のインスタンス変数。

0

他に誰も気づいていないようです:は、リークがかもしれません。

私はfooはIVARとretainプロパティの両方であることを前提としています:自体に漏れない、ということ

-(void)bar { 
    foo = [[NSObject alloc] init]; 
    self.foo = nil; 
} 

@interface Foo : NSObject { 
    NSObject * foo; 
} 
@property (nonatomic, retain) NSObject * foo; 
@end 

はのは、あなたのコードは次のようになりますしましょうが提供された場合、fooはゼロから始まり、で始まりました。それはあなたがそれらの一方のみを呼び出すことを想定しているためfoo = [[Foo alloc] init]よう

-(void)baz { 
    self.foo = [[NSObject new] autorelease]; 
} 

-(void)fubar { 
    [self baz]; 
    [self bar]; 
} 

スタッフは、init -methodsで、一般的に安全なのでfooがされている:あなたは、いくつかのより多くのコードを追加しましょう - それはそれは漏れないという意味ではありません。最初はnilであることが保証されています。どこにいても、もう少し注意する必要があります。

// Use assertions so it crashes debug builds if it's already set 
assert(!foo); 
foo = [[NSObject alloc] init]; 
self.foo = nil; 

// Or release explicitly. 
[foo release]; 
foo = [[NSObject alloc] init]; 
self.foo = nil; 

// Or just use the setter, which will do the "right thing". 
// This is particularly relevant for "copy" or "assign" accessors. 
self.foo = [[[NSObject alloc] init] autorelease]; 
self.foo = nil; 
関連する問題