8

純粋な ARC コーディングの経験があります。コンパイラの機能として、必要に応じて適切な保持/解放呼び出しを配置する Objctive-C メソッド ファミリを尊重します。

allocmutableCopy、で始まり、新しいオブジェクトcopyを作成するすべてのメソッド。newそれらは保持カウントを増やします。結果として、ARC は必要がなくなったときにすべてのポインター (およびそれに関連付けられたオブジェクト) を解放します。

命名規則に従わないメソッドを記述すると、問題が発生する可能性があると思います。たとえばnewCustomer、最初のバージョンでは自動解放されたオブジェクトを返し、2 番目のバージョンでは返さないようなメソッドを記述した場合、何が起こるでしょうか?

特に、私の質問は次のとおりです (同じ理由に属します)。

  • 呼び出し元と呼び出されたコードの両方が ARC でコンパイルされている場合はどうなりますか?
  • (a)呼び出しコードが ARC でコンパイルされ、呼び出しコードが非 ARC でコンパイルされるとどうなりますか?
  • (b)呼び出されたコードが ARC でコンパイルされているのに、呼び出しコードが非 ARC でコンパイルされている場合はどうなりますか?

ARCが内部でどのように機能するかを示す回答をいただければ幸いです(objc_releaseobjc_retainAutoreleasedReturnValueなど)。

前もって感謝します。

4

2 に答える 2

12

名前付きのメソッドはメソッド ファミリnewCustomerに分類されるため、保持されたオブジェクトを返すものとして暗黙的にマークされます。呼び出し元と呼び出されたコードの両方が ARC でコンパイルされている場合、ARC は余分な保持と呼び出し元での解放のバランスを取ります。new

そのような関数またはメソッドから戻るとき、ARC は、すべてのローカル スコープを離れる前に、return ステートメントの評価の時点で値を保持します。

そのような関数またはメソッドから戻り結果を受け取ると、ARC は、ローカル値の通常の最適化に従って、その値が含まれている完全な式の末尾にある値を解放します。

ソース

newCustomer手動参照カウントで実装されていて、命名規則に違反している (つまり、保持されたオブジェクトを返さない) 場合、呼び出し元は状況に応じてオーバー リリースまたはアンダー リリースのいずれかになります。

呼び出し元が ARC を使用している場合、返されたオブジェクトはnewCustomerオーバーリリースされ、プログラムがクラッシュする可能性があります。これは、呼び出しコードが上記のプロセスの後半に参加し、その前に対応する保持が実行されていないためです。

呼び出しコードが ARC でコンパイルされていないが、呼び出されたコードが ARC でコンパイルされている (したがって、保持されたオブジェクトを返すことを正しく実装している) 場合、動作は、命名規則に従うプログラマーに依存します。戻り値を解放すると、オブジェクトの参照カウントは正しく管理されます。ただし、プログラマーが自分のnew...メソッドが命名規則に違反していると考え、呼び出し元のコードにリリースを手動で挿入しなかった場合、返されたオブジェクトはリークします。

全体として、Martin R. がコメントで指摘しているように、重要な決定は、手動参照カウントを含む任意の環境で命名規則に従っているかどうかです。

于 2013-04-01T16:53:57.010 に答える
2

他の言語と同様に、言語の基本的な前提に違反すると、未定義の動作の領域に迷い込んでしまいます。将来のある時点で、Apple-new...は参照カウント方法の内部を変更する可能性があります。予想される用途に準拠したコードが機能することを確認するのは Apple 次第ですが、準拠していない用途についてはそうしません。

特定のシステムで実行されている特定のバージョンのコンパイラの実際の動作を知る必要がある場合は、それをテストする必要があります。他のコンパイラやランタイムのバージョンでも動作が同じであると想定しないでください。

結局、未定義の動作は未定義の動作です。それに依存するコードを作成すると、最終的には微妙で診断が難しい欠陥の影響を受けます。

于 2013-04-01T16:57:01.683 に答える