6

iPhone アプリでメモリ警告が表示されるので、Instruments の助けを借りて、リークを見つけたり、メモリをより効率的に使用したりしようとしています。とりわけ、自動解放されたオブジェクトをすべて取り出して、手動の alloc/init/release オブジェクトに置き換えようとしています。ただし、一部の API 呼び出しには「init」バージョンがないようです (以下のコードを参照)。確かに、いくつかの基本的な誤解があります。

  1. API を「呼び出し」て、本質的に自動解放されたオブジェクトを取得した場合、これらのオブジェクトが Instruments でリークとして表示される可能性はありますか? Instrumentsでこの動作が見られるようです。

  2. 2 に「はい」の場合、「非自動リリース」の代替手段がなく、必要な API を使用している場合は無視する必要がありますか? また、このコードが頻繁に呼び出される場合、アルゴリズムを完全に再考する必要がありますか?

これは、頻繁に呼び出される私のアプリケーションのユーティリティ コードです。基本的に、2 つの日付が意味のある「等しい」かどうかを判断します。コメントアウトしたコードを残したので、コードベースで行っている改善の種類を確認できます。この DIDは、NSDate を手動で作成 (およびリリース) し始めたときに、その後 Instruments で実行したときにメモリリークを減らしました。助けた。ただし、漏れていると思われる日付コンポーネントオブジェクトがまだあります...しかし、それはAPI呼び出しです(コードのフォーマットについては申し訳ありませんが、SOで改善できないようです):

+ (BOOL)isDayEqualToDay:(NSDate*)date anotherDate:(NSDate*)anotherDate
{

    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];  
    //NSCalendar *cal;  
    NSDateComponents *componentsFromDate, *componentsFromAnotherDate;   
    NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;    
    //cal = [NSCalendar currentCalendar];
    componentsFromDate = [cal components:unitFlags fromDate:date];
    componentsFromAnotherDate = [cal components:unitFlags fromDate:anotherDate];

    BOOL bDatesEqual = ([componentsFromDate year] == [componentsFromAnotherDate year] && 
                        [componentsFromDate month] == [componentsFromAnotherDate month] && 
                        [componentsFromDate day] == [componentsFromAnotherDate day]);

    [cal release];

    return bDatesEqual;

    /*
    return (
        [componentsFromDate year] == [componentsFromAnotherDate year] &&
        [componentsFromDate month] == [componentsFromAnotherDate month] && 
        [componentsFromDate day] == [componentsFromAnotherDate day]
    );*/
}

componentsFromDate と componentsFromAnotherDate がリークとして表示されていると思いますが、本質的に NSData API 呼び出し (自動リリース) から返されたオブジェクトだけがあります。これをより効率的にするために他に何ができるのかわからず、Instruments を最適に使用する方法についての私の理解に疑問を呈しています。提案?

4

2 に答える 2

4

自動解放されたオブジェクトは、メモリリークとして表示されないはずです。ただし、APIの内部にメモリリークがある場合があります。アップルにバグレポートを提出する必要があります。NSCalendarやNSDateComponenetsのような新しいクラスは特に疑わしいものです。

保持と自動解放については、一般的なルールとして、タイトなループに入っていない限り問題はありません。その場合、イベントが終了せずにタイトループが何千回も進行している場合は、自動解放プールを「クリーンアップ」しないことを意味します。

于 2009-03-24T22:06:07.323 に答える
3

GCD のようなものを使用する場合、自動解放プールがありますが、デフォルトの自動解放プールがいつ空になるかを知る方法はありません。atoreleased オブジェクトが解放されていないと確信している場合は、使用しているスレッド API を理解していることを確認してください。メモリが適切に機能する場合、GCD 呼び出し (dispatch_async) によって自動解放プールが整理されますが、プールの実際の排出には時間がかかる場合があります。一方、NSOperations を使用すると、自動解放プーリングを自分で行うことができます。

10 秒間隔に依存する Instruments でのメモリ リーク検出が、自動解放プールが空になるまでの遅延が長引くため、偽のメモリ リーク警告になるのを見てきました。したがって、問題のあるコードを次のようにラップしてみてください。

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
... [your code] ...
[pool drain];

すべての自動リリースを手動リリースに置き換えようとすることはお勧めしません。autorelease を使用すると、バランスのとれた保持/解放コール カウントが 1 つの場所で得られます。私の意見では、オブジェクトを作成してすぐに自動解放することで、多くのメモリ バグを防ぐことができます。すばやく、簡単に。手動リリース コールを使用すると、リリースするのを忘れてしまいます。手動リリースを行う場合、特にエラー状態は注意が必要です。

自分でプールを作成すると、より詳細な制御が可能になり、割り当て集中型の作業中には、独自のプールを作成してドレインすることが有益な場合があります。しかし、いつものように、仮定をせずに試してみてください。

于 2011-04-05T11:58:58.033 に答える