2

私はiOS用のCocos2Dを使用してゲームを開発しています。

メニューなどのシーンとメインのゲームシーンがあります。メインシーンには、3つの動的オブジェクトしかありません。これらのオブジェクトは定期的に互いに撃ち合います(これらのオブジェクトが殺されるか、シーンから移動されるまで)。

ここで問題があります。ゲームは常にメモリを消費します。そして、私は自分が間違っていることを知りたいのです。

過剰に保持されたオブジェクトのような明らかなリークはありません。シーンがdealloc編集され、オブジェクトが親から削除されてクリーンアップされ、アニメーションが停止します。

とにかく、メモリはどこかに行き続けます。私は次のコードを使用しています

+ (void) reportMemory
{
    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)
        NSLog(@"Memory in use (in Kbytes): %f", info.resident_size / 1024.0);
    else
        NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}

シーンの各開始時に消費されたメモリの量を確認します。そして、報告された数は常に前のものよりも大きいです。

アロケーションプロファイラーを使用しようとしましたが、正直なところ、有用なものを見つけることができませんでした。リビングバイトの合計は基本的に同じですが、プロセスは常に何かを割り当てたり、割り当てを解除したりします。

あなたは私に何を見ることを提案しますか?基本的に、私の場合、メモリ操作をデバッグする方法についてアドバイスを求めています。

編集(私を助けたもの):

NSZombieEnabledをオンにしたことがわかりました。基本的に、それは一定のメモリ消費量の増加の主な要因でした。いくつかの有用な情報とヒントは@coneybeareの回答にあります

2番目に便利なことは、@ Jackが提案したように、Instruments(Leaks and Allocations)を使用することでした。それは私がいくつかの微妙なリークを見つけるのに役立ちました。

4

3 に答える 3

5

楽器は絶対にあなたの友達です。何かがメモリを食い尽くすと、あなたはそれを見ることができます。

最初に使用する必要があるのは、X 秒ごとにメモリをサンプリングしてリークを表示するリークインストゥルメント (割り当てではありません) です。

特定の認識されたリークをクリックすると、確認できます

  • Aリークが見つかった責任ある呼び出しチェーン
  • Bの小さな矢印をクリックすると、メモリ リークの正確な進行状況を確認できます (malloc されたとき、保持されたとき、解放されたときなど)。

Xcodeのリーク

これで十分でない場合は、割り当て手段を選択すると、左側にMark Heapというラベルの付いたボタンが表示されます。このボタンは、クリックするたびにヒープのスナップショットを作成し、正確な違いを表示できるため、メモリが割り当てられ、2 つの瞬間の間に解放されないかどうかを確認できます。 .

ここに画像の説明を入力

これらを使用して、メモリ関連の問題を常に見つけることができました。

于 2012-06-04T14:02:47.820 に答える
3

次のようにテクスチャ キャッシュを調べることから始めます。

[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];

各シーンの開始時にそれを行います。テクスチャは実際にメモリを大量に消費する可能性があります。おそらく、何らかのテクスチャを保持している可能性があります (これを行う簡単な方法は、どこかのキャッシュにもある spriteFrames を使用することです)、または保持された参照がデータ モデルのどこかにある可能性があります。これが私の #if DEBUG memoryWarning デリゲートです:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    CCLOG(@"AppDelegate<applicationDidReceiveMemoryWarning> : before purging all caches");
    [[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
    [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
    [[CCDirector sharedDirector] purgeCachedData];
    CCLOG(@"AppDelegate<applicationDidReceiveMemoryWarning> : after purging all caches");
    [[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
}
于 2012-06-04T14:37:35.587 に答える
2

Cocos 階層内にオブジェクトを保持していないことを確認してください。オブジェクトをクリーンアップするための Cocos 組み込みメソッドは、Cocos がオブジェクトの単独の制御と所有権を持っていない限り、常に機能するとは限りません。スプライトまたはレイヤーを保持 iVar として保存し、通常の Cocos 所有権を超えて参照カウントを増やすと、期待どおりにクリーンアップされない場合があります。assignこのため、Cocos オブジェクトへのポインタを保持するときは常にプロパティを使用します。

于 2012-06-04T16:05:06.170 に答える