2

私はdebug_newを使用してメモリリークを見つけています。オブジェクトを削除していますが、debug_newにリークの痕跡が表示されません。

メモリの断片化に関するいくつかのスレッドを読みました。しかし、私はまだ混乱しています。この時点で、フレームワークをテストしていて、簡単なテストを行っています。次のような新しいオブジェクトを作成します。

if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space)){
    artemis::Entity& e = world->createEntity();
    e.addComponent(new PositionComponent(posX,posY));
    e.addComponent(new MovementComponent(500,0));
    e.addComponent(new SpriteComponent(TextureManager::getInstance().getTexture("bullet.png")));
    e.addComponent(new ColliderComponent(10,10));
    e.refresh();
    e.setGroup("BULLET");
}

これらの「コンポーネント」は、「EntityManager」と呼ばれるマネージャーで管理されます。このマネージャーは、エンティティオブジェクトを再利用しますが、エンティティが「プール」に送り返されるときにコンポーネントを破棄します。私はこれをテストしましたが、プールに利用可能なエンティティがない場合にのみ、新しいエンティティが作成されます。

上記のコードでわかるように。この簡単なテストでは、パターンは同じです。それでも、アロケータは以前に使用されたメモリを再利用する代わりに、新しいメモリを使用し続けます。スペースバーのヒットごとに(フレームの1/60ごとに)数千を作成すると、メモリが2ギガのスペクトルになりました。コンポーネントはそれほど大きくはありません。例えば:

class ColliderComponent : public artemis::Component{

    public:
    int width,height,collidionsId;

    ColliderComponent(int width, int height){
        this->width = width;
        this->height = height;
    }
};

これまでのところ、ほとんどのコンポーネントはintの単純な「コレクション」です。彼らはかなり軽量です。以前に割り当て/解放されたメモリの一部を確実に再利用する必要があります。しかし、そうではありません。

多分私は何かが欠けています。誰かが何が起こっているのかについて別の考えを持っていますか?そして、良い(無料の)メモリプロファイラーはありますか?それが私のコンポーネントのせいではない場合、欠陥はどこかにあるに違いありません。私はこの時点でそれを単に見ることができず、控えめに言ってもイライラします。

編集:大きなリークを引き起こした別の部分を見落としていたようです。これは明らかに私自身の愚かな過ちでした。

これが原因でした:e.setGroup( "BULLET");

「BULLET」はポインタとして保存され(これを再設計する必要があります)、エンティティIDのインデックスにある既存の文字列へのポインタを上書きしていました。なぜこれを見落としたのかわかりませんが、メモリ割り当ては安定しています!

スマートポインタを使用することもできましたが、これまでのところ、これから多くのことを学んでいます。何かを達成したような気がする=D

4

2 に答える 2

1

にオーバーロードnewされた演算子が表示されないColliderComponentため、常にヒープから割り当てて、メモリをに割り当てていると思いますEntityManager。これは間違いなくリークのように見えますEntityManagerが、破壊されるとすぐに消えます。

編集:私はあなたのコードが今どのように機能するかについてもっと理解しています。コンポーネントはあなたによってキャッシュされませんEntityManager、ただEntityです。

于 2012-07-26T01:30:29.900 に答える
0

タスクマネージャーを使用してメモリ消費量を評価しているとのことですが、ほとんどのメモリマネージャーは、解放されたメモリをオペレーティングシステムにすぐに返しませんが(これはかなりコストのかかる操作です)、アプリケーション自体で使用できるメモリを保持します。そのため、アプリケーションのメモリマネージャー(C ++ランタイムの一部)は、解放したブロックを空きとしてマークし、後で別のメモリ要求が発生したときに再利用できるようにします。

これには、ランタイムのメモリマネージャがメモリを解放して再取得するためにOSを常に呼び出す必要がないため、パフォーマンス上の利点があります。

于 2012-07-26T00:56:45.667 に答える