web-dev-qa-db-ja.com

NSMutableArrayメモリ管理

NSMutableArray *a1 = [[NSMutableArray alloc] init];
NSMutableArray *a2 = [NSMutableArray array];

TempObj *obj = [[TempObj alloc] init]; //assume this line is repeated for each obj
[a1 addObject:obj];
[a1 addObject:obj2];
[a1 addObject:obj3];
[a1 addObject:obj4];

[obj release];
[obj2 release];
[obj3 release];
[obj4 release];

[a1 release];

さて、a2は自動リリースobjなので、releaseを呼び出す必要はありませんか?また、自動解放オブジェクトを取得したことをどのようにして知ることができますか?

そして、a1の場合、最初に配列をループして各オブジェクトを解放する必要はありませんか? [a1removeAllObjects]を呼び出した場合はどうなりますか。それは[[a1objectAtIndex:#] release]を呼び出しますか;

それらを配列に追加した後、それらのオブジェクトを解放することになっていますか?

24
chicken

オブジェクトを配列に追加すると、そのオブジェクトに対してretainが呼び出されます。そのオブジェクトへのポインタを解放しないと、リークになります。配列を解放すると、以前はreleaseが呼び出されていたため、配列が保持しているすべてのオブジェクトに対してretainが呼び出されます。

自動リリースとリリースに関しては、(ドキュメントを読むことを除いて)確実に知る唯一の方法はメソッドの名前です。一般的なルールは、オブジェクトを割り当てなかった場合、オブジェクトを解放する責任はないということだと思います。

オブジェクト作成メソッドに関しては、すべての便利なメソッド(array:arrayWithObjects:arrayWithArray:など)自動解放されたオブジェクトを返します。ただし、対応するinitメソッド(init:initWithObjects:initWithArray:など)しないでください-それらを呼び出す場合は、返されたオブジェクトでreleaseを呼び出す責任があります。

ここで、このトピックに関する他のいくつかの質問を思い出しているようです。より詳細な説明を探してみてください。

45
Andy

Objective-Cのメモリ管理は、保持解放という観点からではなく、所有権と考える方が簡単です。オブジェクトを配列に追加すると、配列はオブジェクトの共同所有者になり、メモリを適切に管理する責任があります。所有者(投稿したコードが含まれているオブジェクト)がオブジェクトに対してreleaseを呼び出すと、所有権が放棄され、配列が唯一の所有者になります。

Appleは、Cocoaで所有権がどのように機能するか(オブジェクトでreleaseを呼び出す責任があるかどうかを知る方法を含む)に関する優れた入門書を持っています: Cocoaのメモリ管理プログラミングガイド 。ココアを使いたいなら必読です。

12
Chuck

覚えておくべき基本的なことはこれです:「init」、「retain」または「copy」へのすべての呼び出しと「release」または「autorelease」への対応する呼び出しのバランスをとる必要があります。あなたが知る必要があるのはそれだけです。

あなたの例では、a1に「init」の呼び出しがあったので、どこかに「release」を置く必要があります。 「obj」と同じです。他の何かで「init」、「retain」、または「copy」を呼び出さなかったので、他の何かで「release」または「autorelease」を呼び出す必要はありません。

0
Jason Harris