2010-12-11 15 views
3

私は長年のJava開発の後にObjective-Cでプログラミングを始めています。私が少し苦労している1つの問題は、メモリ管理です。特に、書籍やオンラインのほとんどの例では、例外によってメモリリークが考慮されていないようです。たとえば、次の方法を検討してください。@finally節に[pool drain]を入れる必要がありますか?

メモリリークの可能性を防ぐために、上記のように書き換えないでください。

-(void) doSomething 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; 

    @try { 

     // Allocate some autoreleased objects here 

     NSString *data = [NSString [email protected]"Hello"]; 

     // Do some work, exception could be thrown 

     [PotentialExeptionThrower maybeThrowException]; 

    } @finally { 
     // Clean up autorelease objects 

     [pool drain]; 
    } 
} 

上記のコードは、@ try- @ catchのために効率が悪いですか?

ありがとうございます!

答えて

1

ありませんあなたはいけません。私はあなたの経験が何年ものJavaに汚染されていることを知っています、あなたは例外に近づく方法を変える必要があります。

名前が示すように、例外はCocoaアプリケーションの通常のプログラムフローの一部ではありません。例外は、開発者が行ったエラーをキャッチするために使用されます。YOUの処理前にアプリが出荷されます。単体テストでデータモデルをカバーし、最後のすべてを吐き出します。

たとえば、NSInvalidArgumentExceptionは、プロダクションコードに没頭すべきではありません。ユニットテストを使用して、ユーザ入力を検証し、ロジックのエッジケースをカバーしてください!

あなたの間違いではないエラーに対しては、代わりにNSErrorインスタンスを使用する必要があります。エンドユーザーに適したローカライズされた説明の優れた特性を持っています。 NSErrorには、「キャンセル」または「再試行」など、適切な回復オプションを処理する機能があります。

私はここにiOSの例外とエラーに長いブログ記事を書かれている:リンクのhttp://blog.jayway.com/2010/10/13/exceptions-and-errors-on-ios/

+0

おかげで、私はあなたのブログの記事が非常に役に立ちました。あなたはJavaの背景について正しいです。例外処理は、Objective-Cコードを@try @catch @finallyで埋めるJavaプログラミングの不可欠な部分です。私は今正しいパターンをgrokし始めている。 –

2

これは、this Apple documentで説明しています。あなたはそれをする必要はありません。要点は、下位のプールが排水されている場合、上回っていない上位プールも自動的に排水されることです。そう、はい、自動リリースされたオブジェクトのリリースは例外によって遅れますが、最終的にリリースされます。

したがって、説明することができる:あなたはそう頻繁にプールを設定する必要はありません

NSAutoreleasePool* A = [[NSAutoreleasePool alloc] init]; 
NSAutoreleasePool* B = [[NSAutoreleasePool alloc] init]; 

    .... do many things. Put things in B ... 

NSAutoreleasePool* C = [[NSAutoreleasePool alloc] init]; 

    .... do many things. Put things in C ... 

[A drain]; // it automatically drains B and C, too! 

注意。すべての方法でそれを設定することは、確かに過度のことです。通常、Instrumentによる実際の測定では、メソッドに保持されている自動解放されたオブジェクトが非常に多い場合を除いて、ローカルプールの追加を開始しません。

0

自動解放プールは特別です。「新規/ alloc/copyの場合は、必ず解放しなければなりません」というメッセージは厳密には適用されません。自動解放プールを作成すると、それは特別なスタックに置かれます。プールを排水するのを怠ると、スタック内のプールが排水されると排水されます。キャッチブロックでの排水は必要ではありませんが、例外により排水が遅れることがあります。詳細は "Scope of Autorelease Pools and Implications of Nested Autorelease Pools"をお読みください。

4

一般的には:いいえ、そうしないでください。プールは、例外パス上で流出してはなりません。代わりに、親プールがあるときに自動的に排水されます。 (最後の句で解放されているので、コール階層の上にあるコードが例外を検査しようとすると、クラッシュする可能性があります)

例外は、最も外側のプールは、マルチスレッドコードで発生する可能性が最も高いプールです。この場合、コードで例外が生成されることが予想される場合は、例外をキャッチしてスカッシュまたは処理し、自動解放プールを排除する必要があります。システムフレームワークによって生成された例外がプログラミングエラーを示し、プログラムを未定義の状態にするため、実際には例外を発生させないと受け入れられると考えられます。

2

Mac OS XおよびiOSアプリケーションの例外は、一般的に回復不可能なプログラマエラーを示すために予約されていることに注意してください。

フレームワークで例外をスローすると、の動作は定義されていません

例外は、フロー制御に使用されるではなく、です。

(他の誰かが述べたように - 例外ケースでプールを解放していない親のプールがそれをクリーンアップします。。)

関連する問題