web-dev-qa-db-ja.com

7 MBのメモリしか割り当てられていないのにメモリ警告が表示されるのはなぜですか?

IOSアプリをiPodtouchデバイスで実行していますが、以下に示すように、合計割り当てのピークがわずか7 MBであっても、メモリの警告が表示されます(これは次の場合に発生します)ゲームシーンがプッシュされます):

low memory warning

奇妙なと思うのは:

  • 左のピーク(時間0.00)は、割り当てられた20 MBのメモリ(紹介シーン)に対応しますが、これにもかかわらず、メモリの警告は表示されません。

  • 中央のピーク(時間35.00)は、割り当てられたメモリの約7 MBに対応し(ゲームシーンがプッシュされています)、メモリ警告を表示します。

合計メモリが7MBしかないのに、なぜこれらの警告が表示されるのかわかりません。これは正常ですか?どうすればこれを回避できますか?

Density peaks

割り当て密度を見ると、次のスキーマがわかります。これは、イントロシーンがプッシュされている瞬間(0.00)とゲームシーンがプッシュされている瞬間(35.00)の間に大きな違いはありません。 密度のピークが類似しているので、メモリの警告は私が見つけることができない他の何かによるものだと思います

編集:

代わりに「アクティビティモニター」を使用するという提案に従っていますが、残念ながら、30 MBのメモリのみが割り当てられているゲームシーンをロードすると、アプリがクラッシュします。これがアクティビティモニターレポートです。

Activity monitor report

レポートを見ると、実際のメモリ使用量の合計は約105MBであることがわかります。これがRAMメモリを参照し、私のモデルが 256 MB のRAM APPのクラッシュまたはメモリリークの問題を引き起こします。

リークモニターを実行しましたが、アプリにリークが表示されません。他のすべてのアプリも強制終了しました。

ただし、レポートを分析すると、アプリに関連付けられている驚くべき167 MBの仮想メモリ値が表示されます。これは正常ですか?その値はどういう意味ですか?これがクラッシュの理由でしょうか?コードのどの領域がこれに関与しているのかをどのように検出できますか?

Virtual memory

私のiPodは第4世代モデルで、容量(メモリ)は6.4 GB、空きメモリは290MBだけです。これが仮想メモリ ページング のパフォーマンスに何らかの影響を与えるかどうかはわかりません。

編集2:SpringBoardについても詳しく調べましたが、仮想メモリの使用量は180MBです。これは正常ですか? SpringBoardがオブジェクトの自動解放を担当していることを示唆しているように見えるいくつかの 質問/回答 を見つけました(画面とホームボタンを管理するプロセスである必要がありますが、それがあるかどうかはわかりませんメモリ管理にも関係します)。これは正しいです?

別のメモ。 ARCを使用しています。ただし、明らかなメモリリークはなく、XCodeはコンパイルされたバイナリにrelease/dealloc/retain呼び出しを追加するコードを変換する必要があるため、これが問題と大いに関係があるかどうかはわかりません。

編集3:前に述べたように、私はARCとCocos2d(2.0)を使用しています。私はアクティビティモニターで遊んでいます。 GameCenter認証メカニズムを削除すると、アクティビティモニターが正常に実行されることがわかりました(新しい疑問:他の誰かが同様の問題を抱えていましたか?GameCenter認証ビューはどこかに保持されていますか?)。しかし、GameSceneの前のさまざまなシーン間を前後に移動するたびに(初期シーン->キャラクター選択->惑星選択->キャラクター選択->惑星選択->など。->キャラクター選択..)に気づきました。 REAL MEMORYの使用量が増加します。しばらくすると、メモリの警告が表示され始め、アプリがiOSによって強制終了されます。今の質問は:

->シーンを正しい方法で置き換えていますか?私はさまざまなシーンから次のように呼びます。

[[CCDirector sharedDirector] replaceScene: [MainMenuScene scene]];

私は静的ライブラリとしてCocos2d 2.0を持っていますそしてreplaceSceneのコードはこれです:

-(void) replaceScene: (CCScene*) scene
{
    NSAssert( scene != nil, @"Argument must be non-nil");

    NSUInteger index = [scenesStack_ count];

    sendCleanupToScene_ = YES;
    [scenesStack_ replaceObjectAtIndex:index-1 withObject:scene];
    nextScene_ = scene; // nextScene_ is a weak ref
}

どういうわけかシーンが適切に割り当て解除されないのだろうか。クリーンアップメソッドが呼び出されていることを確認しましたが、CCLayerのdeallocメソッドにCCLOG呼び出しを追加し、静的ライブラリを再構築しました。その結果、deallocメソッドが呼び出されていないように見えます

これは正常ですか? :D

他の人にも 同様の問題 があることがわかりました。 保持サイクルと自己ブロックに関係があるのだろうかと思っています。 編集3から、誰かが私が何であるかをすでに教えてくれない限り、私は本当にこれを研究するのに時間を費やす必要があります間違っている:-)

22
mm24

コンソールにプロセスの有効なメモリ使用量の印刷を追加することで、これを解決しました。このようにして、アプリプロセスで使用される実際のメモリを正確に測定することができました。使用された実際のメモリが機器に表示されたものと一致しなかったため、機器の使用は不正確であることが判明しました。

このコードは、効果的なメモリ使用量を取得するために使用できます。

-(vm_size_t)report_memory
{    
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(),
                                   TASK_BASIC_INFO,
                                   (task_info_t)&info,
                                   &size);
    if( kerr == KERN_SUCCESS ) {
    } else {
        NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
    }
    return info.resident_size;
}
0
mm24

すべてのアプリとプロセスで共有されるすべてのメモリ容量はiOSで実行されます。そのため、他のアプリは大量のメモリを使用する可能性があり、アプリもメモリ警告を受け取ります。十分でなくなるまで、メモリの警告が表示されます。

アプリのメモリで実際に何が起こるかを理解するには、

  1. リークを使用してアプリのプロファイルを作成します(ARCは、リークがないこと、つまり自己キャプチャの問題がないことを保証するものではありません)。

  2. ヒープショット分析を使用します(ここで簡単に説明します http://bentrengrove.com/blog/2013/4/26/heapshot-analysis

そして、iOSのメモリと仮想メモリに関するこの投稿をチェックしてください: http://liam.flookes.com/wp/2012/05/03/finding-ios-memory/

3
ilya