38

retainCountまたは、夏休みに使わなかった理由

この投稿は、SO の周りに浮かんでいる関連情報を統合するために、その悪名高いメソッドの理由と理由についての詳細な記事を募集することを目的としていretainCountます。*

  1. 基本: を使用しない公式の理由は何retainCountですか? それが役立つかもしれない状況はまったくありますか?代わりに何をすべきですか?**自由に編集してください。

  2. 歴史的/説明的:使用を意図していないのに、Apple がNSObjectプロトコルでこのメソッドを提供するのはなぜですか? retainCountApple のコードは何らかの目的で に依存していますか? もしそうなら、なぜどこかに隠されていませんか?

  3. 理解を深めるために: オブジェクトの保持カウントがユーザー コードから想定されるものと異なる理由は何ですか? このような違いを引き起こすフレームワーク コードで使用される可能性のある標準的な手順の例を挙げていただけますか? 保持カウントが新しいユーザーが期待するものと常に異なる既知のケースはありますか?

  4. 他に言及する価値があると思われるものはありますretainCountか?


* Objective-C と Cocoa を初めて使用するコーダーは、参照カウント スキームに取り組むか、少なくとも誤解することがよくあります。チュートリアルの説明では、(これらの説明によると) 、 、 などを呼び出すと 1 ずつ増加し、呼び出すと 1 ずつ減少する保持カウントについて言及しているretain場合alloccopyありますrelease(将来のある時点で を呼び出すとautorelease)。

新進の Cocoa ハッカーであるクリスは、オブジェクトの保持カウントをチェックすることがメモリの問題を解決するのに役立つという考えを非常に簡単に得ることができましたretainCount。クリスはretainCountいくつかのオブジェクトを呼び出しましたが、これは高すぎて、あれは低すぎて、一体何が起こっているのでしょうか?! それで、Kris は SO に投稿します。そして、<bold>、<large> の文字の群れが降りてきて、「そんなことはやめてください! 結果に頼ることはできません.」と言っています。

これが FAQ に変わることを願っています。それは、新しいココア ヘッズがretainCount.

** 私はこれをあまり広くしたくありませんが、経験からの具体的なヒントや、保持とリリースのペアリングの検証/デバッグに関するドキュメントがここで適切かもしれません.

***ダミーコードで; 明らかに、一般大衆は Apple の実際のコードにアクセスできません。

4

2 に答える 2

29

基本:retainCountを使用しない公式の理由は何ですか?

retainCount自動解放管理は最も明白です。 によって表される参照の数が、ローカルまたは外部 (セカンダリ スレッド上、または別のスレッドのローカル プール内) の自動解放プールにあることを確認する方法はありません。

また、リークやより高いレベルの参照カウント、および自動解放プールが基本レベルでどのように機能するかについて問題を抱えている人もいます。彼らは、適切な参照カウントを (あまり) 考慮せずに、または参照カウントを適切に学習せずにプログラムを作成します。これにより、プログラムのデバッグ、テスト、および改善が非常に困難になります。修正には非常に時間がかかります。

(クライアント レベルで) その使用を思いとどまらせる理由は 2 つあります。

1) 値は非常に多くの理由で異なる場合があります。スレッドだけでは、それを信頼できない十分な理由があります。

2) 正しい参照カウントを実装する必要があります。retainCount不均衡な参照カウントからあなたを救うことは決してありません。

それが役立つかもしれない状況はまったくありますか?

実際、独自のアロケータまたは参照カウント スキームを記述した場合、またはオブジェクトが 1 つのスレッド上に存在し、それが存在する可能性のあるすべての自動解放プールにアクセスできる場合は、意味のある方法で使用できます。外部 API と共有します。これをシミュレートする簡単な方法は、スレッドが 1 つ、自動解放プールがゼロのプログラムを作成し、「通常の」方法で参照カウントを行うことです。「学術的」な理由以外で、この問題を解決したり、このプログラムを作成したりする必要があるとは考えにくいでしょう。

デバッグの補助として: これを使用して、保持カウントが異常に高くないことを確認できます。このアプローチを採用する場合は、実装の差異に注意してください (一部はこの投稿で引用されています)、それに依存しないでください。テストを SCM リポジトリにコミットすることさえしないでください。

これは、非常にまれな状況で有用な診断になる場合があります。以下の検出に使用できます。

  • 過剰保持: プログラムが割り当てに到達できる場合、保持カウントに正の不均衡がある割り当ては、リークとして表示されません。

  • 他の多くのオブジェクトから参照されるオブジェクト: この問題の 1 つの例は、マルチスレッド コンテキストで動作する (変更可能な) 共有リソースまたはコレクションです。このリソース/コレクションへの頻繁なアクセスまたは変更は、プログラムの実行に重大なボトルネックをもたらす可能性があります。

  • 自動解放レベル: 自動解放、自動解放プール、保持/自動解放サイクルにはすべてコストがかかります。メモリの使用や増加を最小化または削減する必要がある場合は、このアプローチを使用して過剰なケースを検出できます。

Bavarious のコメントから (以下): 高い値は、無効な割り当て (dealloc されたインスタンス) を示している可能性もあります。これは完全に実装の詳細であり、製品コードでは使用できません。ゾンビが有効になっている場合、この割り当てを通知するとエラーが発生します。

代わりに何をすべきですか?

でメモリを返す責任がない場合self(つまり、アロケータを作成していない場合) は、そのままにしておいてください。それは役に立ちません。

適切な参照カウントを学ぶ必要があります。

release と autorelease の使用法をよりよく理解するには、いくつかのブレークポイントを設定し、それらがどのように使用されるか、どのような場合に使用されるかなどを理解してください。参照カウントを正しく使用する方法を学ぶ必要がありますが、参照カウントが役に立たない理由を理解するのに役立ちます。 .

さらに簡単です。Instruments を使用して割り当てと参照カウントを追跡し、アクティブなプログラム内のいくつかのオブジェクトの参照カウントとコールスタックを分析します。

歴史的/説明的: 使用を意図していないのに、Apple が NSObject プロトコルでこのメソッドを提供するのはなぜですか? Appleのコードは何らかの目的でretainCountに依存していますか? もしそうなら、なぜどこかに隠されていませんか?

主に次の 2 つの理由から、公開されていると考えられます。

1) 管理された環境で適切な参照カウント。アロケーターが使用しても問題ありませretainCountん-本当に。これは非常に単純な概念です。が-[NSObject release]呼び出されると、(オーバーライドされていない限り) ref カウンターが呼び出される可能性があり、retainCount(dealloc の呼び出し後) が 0 の場合、オブジェクトの割り当てを解除できます。これは、アロケータ レベルでは問題ありません。アロケーターとゾーンは (大部分) 抽象化されているため、通常のクライアントにとっては意味のない結果になります。retainCountクライアント レベルで が 0 に等しくならない理由、オブジェクトの割り当て解除、割り当て解除シーケンスなどの詳細については、bbum の解説 (下記) を参照してください。

2) カスタム動作を必要とするサブクラスが利用できるようにするため、および他の参照カウント メソッドが公開されているため。場合によっては便利かもしれませんが、通常は間違った理由で使用されます (不滅のシングルトンなど)。独自の参照カウント スキームが必要な場合は、このファミリをオーバーライドする価値があります。

理解を深めるために: オブジェクトの保持カウントがユーザー コードから想定されるものと異なる理由は何ですか? このような違いを引き起こすフレームワーク コードで使用される可能性のある標準的な手順の例を挙げていただけますか? 保持カウントが新しいユーザーが期待するものと常に異なる既知のケースはありますか?

繰り返しますが、カスタム参照カウント スキームと不滅のオブジェクトです。NSCFStringリテラルは後者のカテゴリに分類されます。

NSLog(@"%qu", [@"MyString" retainCount]); 
// Logs: 1152921504606846975

保持カウントについて他に言及する価値があると思われるものはありますか?

デバッグ支援としては役に立ちません。リーク分析とゾンビ分析の使い方を学び、それらを頻繁に使用してください。参照カウントを理解した後でさえも。


更新: bbum は最近、retainCount is uselessというタイトルの記事を投稿しました。-retainCountこの記事には、大部分のケースでなぜ が役に立たないかについての徹底的な議論が含まれています。

于 2011-04-26T05:19:43.443 に答える
1

一般的な経験則では、この方法を使用している場合は、自分が何をしているのかを確実に理解する必要があります。メモリリークのデバッグに使用している場合は間違っています。オブジェクトで何が起こっているかを確認するために使用している場合は、間違っています。

私がそれを使って、それが役に立つと思った1つのケースがあります。これは、オブジェクトへの参照がなくなったときにオブジェクトをフラッシュしたい共有オブジェクトキャッシュを実行することです。この状況では、retainCountが1に等しくなるまで待機しました。その後、他に何も保持されていないことを認識して解放できます。これは、ガベージコレクション環境では明らかに正しく機能せず、より良い方法があります。しかし、これは私がこれまでに見た唯一の「有効な」ユースケースであり、多くの人が行うことではありません。

于 2011-04-25T22:45:53.063 に答える