2

単純なパーティクルシステムを構築していて、構造体の単一の配列バッファを使用してパーティクルを管理したいと考えています。とはいえ、任意のバッファーからmalloc()とfree()を実行できるC関数が見つかりません。これが私の意図を示すためのいくつかの擬似コードです:

Particle* particles = (Particle*) malloc( sizeof(Particle) * numParticles );
Particle* firstParticle = <buffer_alloc>( particles );
initialize_particle( firstParticle );
// ... Some more stuff
if (firstParticle->life < 0)
    <buffer_free>( firstParticle );

// @ program's end
free(particles);

ここ<buffer_alloc>で、および<buffer_free>は、任意のポインタからメモリチャンクを割り当てて解放する関数です(おそらく、バッファ長などの追加のメタデータを使用します)。そのような機能は存在しますか、および/またはこれを行うためのより良い方法はありますか?ありがとうございました!

4

5 に答える 5

5

ええ、あなたはあなた自身を書かなければならないでしょう。とてもシンプルで本当にばかげていますが、malloc()とfree()を常に使用する場合と比較すると、そのパフォーマンスは悲鳴を上げます。

static const int maxParticles = 1000;

static Particle particleBuf[maxParticles]; // global static array

static Particle* headParticle;

void initParticleAllocator()
{
    Particle* p = particleBuf;
    Particle* pEnd = &particleBuf[maxParticles-1];
    // create a linked list of unallocated Particles
    while (p!=pEnd)
    {
        *((Particle**)p) = p+1;
        ++p;
    }
    *((Particle**)p) = NULL; // terminate the end of the list
    headParticle = particleBuf; // point 'head' at the 1st unalloc'ed one
}

Particle* ParticleAlloc()
{
    // grab the next unalloc'ed Particle from the list
    Particle* ret = headParticle;
    if (ret)
        headParticle = *(Particle**)ret;
    return ret; // will return NULL if no more available
}

void ParticleFree(Particle* p)
{
    // return p to the list of unalloc'ed Particles
    *((Particle**)p) = headParticle;
    headParticle = p;
}

上記のアプローチを変更して、グローバル静的配列をまったく開始せず、ユーザーがParticleAlloc()を呼び出すときに最初にmalloc()を使用できますが、Particlesが返されるときは、free()を呼び出さずに、返されたものを追加します。割り当てられていないパーティクルのリンクリストへの1つ。次に、ParticleAlloc()の次の呼び出し元は、malloc()を使用するのではなく、無料のパーティクルのリストから1つを取得します。フリーリストにこれ以上ない場合はいつでも、ParticleAlloc()関数がmalloc()にフォールバックする可能性があります。または、2つの戦略を組み合わせて使用​​します。これは、両方の世界で実際に最適です。ユーザーがほぼ確実に少なくとも1000個のパーティクルを使用しているが、場合によってはそれ以上のパーティクルが必要になることがわかっている場合は、1000個の静的配列から始めることができます。不足した場合は、malloc()の呼び出しにフォールバックします。そのようにすると、malloc() ' edのものは特別な取り扱いを必要としません。それらがParticleFree()に戻ってきたら、割り当てられていないパーティクルのリストに追加するだけです。プログラムが終了するときに、わざわざfree()を呼び出す必要はありません。OSはプロセスのメモリスペース全体を解放するため、リークされたメモリはその時点でクリアされます。

あなたの質問は「C++」ではなく「C」とタグ付けされていたので、私はCソリューションの形で答えました。C ++では、これと同じことを実装する最良の方法は、Particleクラスに「operatornew」メソッドと「operatordelete」メソッドを追加することです。これらには基本的に上記と同じコードが含まれますが、グローバルな「new」演算子をオーバーライドし(オーバーロードせず)、Particleクラスの場合のみ、グローバルな「new」を置き換える特殊なアロケータを定義します。すばらしいのは、Particleオブジェクトのユーザーは、特別なアロケーターがあることを知る必要さえないということです。通常どおり「new」と「delete」を使用し、Particleオブジェクトが特別に事前に割り当てられたプールからのものであることを幸いにも気づいていません。

于 2012-06-24T21:28:07.260 に答える
1

あ、ごめんなさい。この質問は私だけが見るCです。C++ではありません。それがC++の場合、次のことが役に立ちます。

Boostのプール割り当てライブラリを見てください。

あなたの割り当てのそれぞれが同じサイズであるように私には聞こえますか?粒子の大きさですね。その場合、Boostのプール割り当て関数は非常にうまく機能し、独自に作成する必要はありません。

于 2012-06-24T21:35:56.343 に答える
0

あなたはあなた自身を書くか、すでにそれらを書いた誰かを見つけて彼らが書いたものを再利用しなければならないでしょう。そのシナリオを管理するための標準Cライブラリ、AFAIKはありません。

'バッファ割り当て'コードにはおそらく4つの関数が必要です。

typedef struct ba_handle ba_handle;

ba_handle *ba_create(size_t element_size, size_t initial_space);
void  ba_destroy(ba_handle *ba);

void *ba_alloc(ba_handle *ba);
void  ba_free(ba_handle *ba, void *space);

create関数は、スペースの初期割り当てを行い、情報をの単位で分割するように調整しelement_sizeます。返されたハンドルを使用すると、異なるタイプ(または同じタイプでも数回)に個別のバッファー割り当てを行うことができます。破棄機能は、ハンドルに関連付けられているすべてのスペースを強制的に解放します。

割り当て機能は、使用するための新しいスペースの単位を提供します。無料の関数はそれを解放して再利用します。

舞台裏では、コードは使用中のユニット(おそらくビットマップ)を追跡し、必要に応じて追加のスペースを割り当てたり、最初の割り当てが使い果たされたときにスペースを拒否したりする場合があります。スペースが不足したときに多かれ少なかれ劇的に失敗するように調整することができます(したがって、アロケータがnullポインタを返すことはありません)。明らかに、free関数は、与えられたポインターが、現在使用されているバッファーアロケーターハンドルによって提供されたポインターであることを検証できます。これにより、free()通常は検出されないいくつかのエラーを検出できます(ただし、GNU Cライブラリバージョンなどは、malloc()他のバージョンが必ずしも実行しない健全性チェックを実行するようです)。

于 2012-06-24T21:04:36.983 に答える
0

代わりにこのようなものを試してみてください...

Particle * particles[numParticles];
particles[0] = malloc(sizeof(Particle));
initialize_particle( particle[0] );

// ... Some more stuff
if (particle[0]->life < 0)
    free( particle[0] );

// @ program's end
// don't free(particles);
于 2012-06-24T21:12:16.817 に答える
-1

単純なパーティクルシステムを構築していて、構造体の単一の配列バッファを使用してパーティクルを管理したいと考えています。

私はあなたがそれに答えたと思います:

static Particle myParticleArray[numParticles];

プログラムの開始時に割り当てられ、終了時に割り当てが解除されます。簡単です。または、擬似コードを気に入って、配列を一度にmallocします。なぜ単一のパーティクルを割り当てるのか、システム全体を割り当てないのか、自問するかもしれません。パーティクル配列とインデックスへのポインタを取得するAPI関数を記述します。

于 2012-06-24T21:41:12.083 に答える