2012-02-26 14 views
0

私はlearnig objective-cとiPadアプリをプログラミング中です。私が自分自身を踏み台にして再読しなければならないことの1つは、メモリ管理です。私はそこに行っている...ゆっくりと。すべてのalloc/retainのような基本ルールは、releaseが有益である必要があります。しかし、これは比較的単純コーディングされており、[myArray release]文が必要になりiosでのメモリ管理の理解

NSArray *myArray = [[NSArray alloc] init]; 
myArray = [someNSSet allObjects]; 

...

は、次のコードを取る... 1つの比較的基本的な事は私を見逃さと誰かが説明できるのだろうか。

しかし、私は(の例を見ておくと、確かに、私はあなたが(NSString *)を使用するときに限り、私は理解して、あなたが必要いけないどのように、...広く

NSArray *myArray = (NSArray *)[someNSSet allObjects]; 

を以下の「ショートカット」を使用していました[myArray release]ステートメントを使用しますが、私は理由を理解しない。

可能誰かが説明してもらえますか?

答えて

1

:配列のサイズが0にNSArrayのは不変であることに注意してくださいあるので、メモリのいくつかの量は、アレイ(に割り当てられている

NSArray *myArray = [[NSArray alloc] init] 

は、実際にこのような場合には、それは無意味です! )。 変数myArrayは、予約されたメモリ領域の最初のバイトのアドレスを保持します。

2行目で、[someNSSet allObjects]が格納されているメモリ領域の最初のバイトを指すmyArrayの値を変更します。この時点で、最初の行に作成した配列がどこに格納されているかは分かりません。そしてあなたには漏れがあります。

ライン:あなたはこの時点で任意のメモリを予約していないので、

NSArray *myArray = (NSArray *)[someNSSet allObjects]; 

は、正しいです。 ARCを使用していない場合は、GCをメモリの参照ブロックから遠ざけるためにretainを呼び出すことがあります。他の方法では、オブジェクトの所有者がオブジェクトを解放したときに、BAD_EXECを受け取る可能性があります。例:[myArray objectAtIndex:0]

2
NSArray *myArray = [[NSArray alloc] init]; 
myArray = [someNSSet allObjects]; 

このコードはに漏れているします最初の行に割り当てたNSArrayへの参照が失われているため、と表示されます。 2番目の行にmyArrayに新しい値を割り当てるため、allocは必要ありません。

NSArray *myArray = (NSArray *)[someNSSet allObjects]; 

と、このコード例では、[someNSSet allObjects]myArrayへのポインタの結果を代入していて、返された値を所有していない、完全に罰金ですので、あなたはそれを解放を気にする必要はありません。

プロジェクトではARC(Automatic Retain Counting)を使用することを検討してください。 ARCでは、コンパイラは保持カウントを処理するので、実際には許されません。現在のプロジェクトを変換するリファクタリングがあります。

+0

私は戻り値を所有していません。誰が/何ですか? –

+0

@BenThompson:オブジェクト(newまたはalloc、copyまたはmutableCopy)を作成すると、保持カウントは1になり、所有しています。 メッセージを保持するオブジェクトを送信すると、保持カウントは1だけインクリメントされ、所有者もそれを所有します。自分が所有するオブジェクトを解放するだけです。 –

+1

@Ben:自動解放プールは、 'allObjects'から返されたオブジェクトの所有者である可能性が最も高いです。もう1つの可能性はsetオブジェクトですが、実際には、新しい配列を作成するのではなく、すでに所有しているオブジェクトを単に公開している場合にのみ発生します。しかし、バックグラウンドで何が起こっているのかを理解することを除いて、あなたは誰が物事を所有しているのか心配するべきではありません。あなたがそうしていてもしていなくても、それだけで十分です。 –

2

あなたが言ったように、投稿した最初のコードにはリークがあります。あなたがallocnewcopy、あなたはそれを所有で始まるメソッドを介してオブジェクトを取得する場合、実際には

NSArray *myArray = [[NSArray alloc] init]; 
[myArray release]; 
myArray = [someNSSet allObjects]; 

、あなたはそれを解放する必要がありますので、あなたは、リリースを追加する必要があります。そのため、ここではメソッドallocを使用して取得した配列を解放する必要があります。この規則により、オブジェクトを所有しているときとそうでないときを簡単に知ることができます。覚えておいてください:allocnewまたはcopy

は、第二の例については、次の3つの言葉(allocnewまたはcopy)のいずれかで起動しない方法しかし、配列を得たので、あなたは、オブジェクトを所有していない、とあなたは責任を負いませんそれを解放する。実際に、得られた配列はオートレリースされたオブジェクトです。つまり、保持カウントが現在1であっても、オートレリープールと呼ばれるものが空になったときに自動的に解放されます。

ここに参考文献Memory Management Rulesがあります。最初の行で

+0

は、回答コードの3行目で2行目を反転する方が良いでしょう。(または、releaseではなくautoreleaseを使用してください) – meronix

+0

2行目の 'release'は2行目の' alloc'のバランスをとり、 'myArray'の古い値漏れません。 'myArray'に新しい値を代入する前にそれを行う必要があります。 – sch

+0

はい、もちろんですが、もしそれをリリースすれば、3行目のmyArrayはもう存在しません。それ以上は割り当てられておらず、エラーが出る可能性があります。 allocとreleaseのバランスをとって、これらの2行の間でオブジェクトを使用する必要があります。か否か? – meronix