リソースが自動的に管理されない状況で例外をスローするのは安全ではありません。これは Cocoa フレームワーク (および近隣フレームワーク) の場合で、手動参照カウントを使用します。
例外をスローするrelease
と、スタックをアンワインドしてスキップした呼び出しによってリークが発生します。これは、プロセスが終了するとすべてのリソースが OS に返されるため、回復しないことが確実な場合にのみ、スローするように制限する必要があります。
残念ながら、NSRunLoop
s はそれらに伝播するすべての例外をキャッチする傾向があるため、イベント中にスローすると、次のイベントに再開されます。これは明らかに非常に悪いことです。したがって、単に投げない方がよいでしょう。
ガベージ コレクションされた Objective-C を使用すると、Objective-C オブジェクトによって表されるすべてのリソースが適切に解放されるため、この問題は軽減されます。ただし、Objective-C オブジェクトにラップされていない C リソース (ファイル記述子やmalloc
割り当てられたメモリなど) は引き続きリークします。
だから、とにかく投げないでください。
あなたが言及したように、Cocoa APIにはこれに対するいくつかの回避策があります。リターンnil
とNSError**
パターンはそのうちの2つです。
ARC の説明
ARC ユーザーは、完全な例外安全性を有効にするか無効にするかを選択できます。例外の安全性が有効になっている場合、ARC はスコープが強制終了されたときに強い参照を解放するコードを生成し、コードで例外を安全に使用できるようにします。ARC は外部ライブラリにパッチを適用して例外サポートを有効にすることはありません。そのため、プログラムで例外サポートが有効になっている場合でも、スローする場所 (特にキャッチする場所) に注意する必要があります。
ARC 例外サポートは、 で有効-fobjc-arc-exceptions
または無効にできます-fno-objc-arc-exceptions
。デフォルトでは、Objective-C では無効になっていますが、Objective-C++ では有効になっています。
Objective-C の完全な例外安全性はデフォルトで無効になっています。これは、Clang の作成者が Objective-C プログラムが例外から回復しないことを前提としており、そのクリーンアップに関連して大きなコード サイズのコストと小さなパフォーマンス ペナルティがあるためです。一方、Objective-C++ では、C++ はすでに多くのクリーンアップ コードを導入しており、人々は実際に例外安全性を必要とする可能性がはるかに高くなります。
これはすべて、LLVM Web サイトの ARC 仕様からのものです。