11

本では、次のように言われています:

では、オブジェクトがいつ誰によって所有されているかをどうやって知るのでしょうか?次の例を考えてみましょう。

NSString *str = [[NSString alloc] initWithString:@”Hello”];  
NSString *str2 = str;

この例では、のallocキーワードを使用しているためstr、を所有していますstr。したがって、不要になったときにリリースする必要があります。ただし、 str2は単にを指してstrいるので、所有していません。つまり、使い終わったときにstr2解放する必要はありません。str2

所有権は変数やポインタではなくオブジェクトによるものだと思ったので、「所有する」strまたは「所有するstr2」とは言えません。それはすべて同じです。strstr2[str release][str2 release]

他の説明は次のとおりです。

たとえば、前のセクションで使用した例を考えてみましょう。

NSString *str = [[NSString alloc] initWithString:@”Hello”]; 
NSString *str2 = str;
[str release];
[str2 release]; //---this is not OK as you do not own str2---

str2自分が所有していないオブジェクトを解放できないため、解放しようとするとランタイムエラーが発生します。

[str2 release]それが前に呼び出されれば、実際に使用できます [str release]。これを行うと、行[str release]とエラーが発生します。これはstrstr2両方ともダングリングポインターであり、おそらくrelease最初にオブジェクトに送信されたときに、参照カウントが0になり、deallocすぐに呼び出され、メモリが解放されたためです。 C関数によるfree()

上記は正しいですか、それとも他に修正すべきことがありますか?

4

5 に答える 5

5

メモリ管理の観点からではなく、オブジェクトの所有権の観点から考えてください。オブジェクトの割り当て、保持、またはコピーを行うと、オブジェクトの所有権を取得します。他のオブジェクトではなく、自分が所有するオブジェクトをリリースする責任があります。

あなたの例では、への割り当てstr2はオブジェクトの所有権を取得しませんが、それへの2番目の「所有」参照が本当に必要な場合は、実行する必要があります。その後、実行する[str2 retain]のはエラーではありません[str release]; [str2 release];str2これは、弱い参照として注釈を付けない限り、ARC を使用して自動的に発生することでもあります。(もちろん、この単純なケースでは、不要な保持/解放は、コンパイラによって内部的に最適化される可能性があります。)

于 2012-05-13T13:33:58.173 に答える
3

あなたの推測は正しいです。この本は、ポインターを単純化するために、あいまいな言葉を使用しています (意味は正しいですが)。

strあなたはそれをstr2指し示すオブジェクトを所有しています。

もちろん、これはオブジェクトを1回しか解放できないことを意味します(または、オブジェクトが保持される頻度が高くなります-例では、暗黙的に、 によって1回)、 or (またはその他の手段)でallocそうするかどうかは重要ではありません。strstr2

ただし、実際には、変数を自分が所有しているかのように扱う必要があります。これにより、retain/release ペアの追跡がはるかに簡単になり、その間のどこかでこれらの変数のいずれかの値が変更されていないという事実を当てにすることはできません。

割り当て解除されたインスタンスを指すすべての変数をnil後で設定することをお勧めします (必須ではありません)。

技術的な詳細を少し掘り下げるには (実際には、実装の詳細、プライベート API の成果物として扱う必要があります):

技術的には、誰もオブジェクトを所有していません。オブジェクトには、保持された回数のカウンターがあります (これは、呼び出すことで確認できますanObject retainCountが、そうすべきではありません。特に、いくつかのオブジェクトには偽の保持カウントがあり、それは実際には問題ではないためです)。オブジェクトがalloced の場合、retainCount は 1 です。オブジェクトが送信されるretain(「保持される」) たびに、retainCount は 1 ずつ増加し、送信されるたびにrelease(「解放される」)、retainCount は減少します。 1.

オブジェクトのretainCountがゼロになると、割り当てが解除されます(そしてそのdeallocメソッドが呼び出されます)。

誰がそれらすべてのretain/releaseメッセージを送信したか (およびどの変数を介して) は重要ではありません。

繰り返しますが、これらは実装の詳細です。それらは、Objective-C/Cocoa がメモリ管理を行う方法の成果物です。それらをプライベート API と同様に扱います。好奇心を持つのは良いことですが、内部に依存しないでください。運用コードでは、パブリック API (この場合はretain/releaseおよび自動解放プール) のみを使用してください。

注: 一部のオブジェクト (たとえば、一部のシングルトン) は、デフォルトの保持/解放メソッドをオーバーライドします。retainCount好奇心以外では、オブジェクトから取得した を決して信頼しないでください([UIColor clearColor]たとえば、retainCount を見てください)。

このトピックに関するその他の考えについては、この質問とその回答がおそらく良い要約/出発点です。

そうは言っても、ほとんどすべてのメモリ管理の問題を解決できるARC に切り替えることを検討してください。

于 2012-05-13T13:10:50.003 に答える
2

所有権は、変数やポインターではなく、オブジェクトによるものだと思っていました...したがって、「strを所有している」または「str2を所有している」とは言えません...私たちは、strまたはstr2のいずれかが指すオブジェクトを所有しており、 [str release] または [str2 release] を使用しますが、すべて同じです。

正解です。

著者が「私たちはstrを所有しています」とは、その文字列インスタンスを所有しているということだと思います。ポインターや変数ではありません。理論的には、他のポインターを使用してオブジェクトを解放できます。ただし、通常は、オブジェクトの初期化に使用した変数を使用して解放することをお勧めします。

于 2012-05-13T13:09:39.343 に答える
1

他の答えは間違っているか不完全だと思います。

所有権は、誰がリソースを解放するかによって定義されます。オブジェクトは (通常) 所有していません所有されています。

繰り返しますが、所有者は、メモリの解放を担当する人です。

あなたのコードでstrは、オブジェクトの所有権を宣言していますが、そうでstr2はありません。str2もオブジェクトを所有する ( の所有権を共有する str) には、次のようにする必要がありますretain

[str2 retain];

後で、次のように言うことができます。

[str2 release];

str2の所有権の主張を放棄することであり、同じことが にも当てはまりstrます。

一方、ARC では、リソースへのすべての(参照カウント) ポインターはその共有所有者です。このシナリオでは、すべてのポインターがオブジェクトの参照カウントを追跡し、唯一の所有者であると判断してスコープ外になるとオブジェクトを解放します。

繰り返しますが、所有権はオブジェクトごとではありません。所有権は、オブジェクトのポインターとそれらのポインターの所有者によって決まりますが、それらのポインターが何らかのシナリオで解放される可能性がある場合のみです。ポインターがリソースを解放するシナリオがない場合、ポインターは非所有です。この場合、それらはweakと呼ばれます。

オブジェクトが自分自身を所有している場合、弱いポインターの概念は意味がありません (すべてのポインターが弱いため)。

于 2012-05-13T18:54:29.580 に答える
0

または のいずれstrかを解放するstr2と、メモリの場所strstr2ポイントが解放されます。したがって、同じメモリ位置を指しているため、両方ではなくstrorのみを呼び出す必要があります。str2

ポインターがメモリ内のスペースを指すことができることを知っている限り、変数を「所有する」という意味がわかりません。

于 2012-05-13T13:07:20.667 に答える