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をゼロにすると、前のオブジェクト(自動リリースされた)で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 に答える